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,6 +3,7 @@
3 * Version 1.1.0 released 3 * Version 1.1.0 released
4 ========================= 4 =========================
5 5
  6 + Restrict Monte Carlo simulations in GModelSpatialDiffuseConst to simulation cone (#1674)
6 Use default GTime in GModelSpectral eval() and eval_gradients() methods (#1672) 7 Use default GTime in GModelSpectral eval() and eval_gradients() methods (#1672)
7 Optimise GModelSpatialDiffuseMap::set_mc_cone() method (#1673) 8 Optimise GModelSpatialDiffuseMap::set_mc_cone() method (#1673)
8 Optimise GModelSpatialDiffuseCube::set_mc_cone() method (#1673) 9 Optimise GModelSpatialDiffuseCube::set_mc_cone() method (#1673)
@@ -111,6 +111,11 @@ None @@ -111,6 +111,11 @@ None
111 111
112 8. Model module 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 The GModelSpectral eval() and eval_gradients() methods use an empty GTim() 119 The GModelSpectral eval() and eval_gradients() methods use an empty GTim()
115 object as default time argument since all spectral models are so far time- 120 object as default time argument since all spectral models are so far time-
116 independent. This avoids that a user needs to specify a dummy time argument 121 independent. This avoids that a user needs to specify a dummy time argument
include/GModelSpatialDiffuseConst.hpp
1 /*************************************************************************** 1 /***************************************************************************
2 * GModelSpatialDiffuseConst.hpp - Spatial isotropic model class * 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 * This program is free software: you can redistribute it and/or modify * 7 * This program is free software: you can redistribute it and/or modify *
@@ -86,7 +86,9 @@ protected: @@ -86,7 +86,9 @@ protected:
86 void free_members(void); 86 void free_members(void);
87 87
88 // Protected members 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,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 * @brief Signals whether model contains sky direction 151 * @brief Signals whether model contains sky direction
169 * 152 *
170 * @param[in] dir Sky direction. 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 * @return True. 155 * @return True.
173 * 156 *
174 * Signals whether a sky direction falls within the bounding circle of 157 * Signals whether a sky direction falls within the bounding circle of
src/model/GModelSpatialDiffuseConst.cpp
1 /*************************************************************************** 1 /***************************************************************************
2 * GModelSpatialDiffuseConst.cpp - Spatial isotropic model class * 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 * This program is free software: you can redistribute it and/or modify * 7 * This program is free software: you can redistribute it and/or modify *
@@ -41,7 +41,7 @@ const GModelSpatialDiffuseConst g_spatial_const_seed; @@ -41,7 +41,7 @@ const GModelSpatialDiffuseConst g_spatial_const_seed;
41 const GModelSpatialRegistry g_spatial_const_registry(&g_spatial_const_seed); 41 const GModelSpatialRegistry g_spatial_const_registry(&g_spatial_const_seed);
42 42
43 /* __ Method name definitions ____________________________________________ */ 43 /* __ Method name definitions ____________________________________________ */
44 -#define G_MC "GModelSpatialDiffuseConst::mc(GRan&)" 44 +#define G_MC_NORM "GModelSpatialDiffuseConst::mc_norm(GSkyDir&, double&)"
45 #define G_READ "GModelSpatialDiffuseConst::read(GXmlElement&)" 45 #define G_READ "GModelSpatialDiffuseConst::read(GXmlElement&)"
46 #define G_WRITE "GModelSpatialDiffuseConst::write(GXmlElement&)" 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,6 +60,8 @@ const GModelSpatialRegistry g_spatial_const_registry(&amp;g_spatial_const_seed);
60 60
61 /***********************************************************************//** 61 /***********************************************************************//**
62 * @brief Void constructor 62 * @brief Void constructor
  63 + *
  64 + * Construct empty isotropic spatial model.
63 ***************************************************************************/ 65 ***************************************************************************/
64 GModelSpatialDiffuseConst::GModelSpatialDiffuseConst(void) : 66 GModelSpatialDiffuseConst::GModelSpatialDiffuseConst(void) :
65 GModelSpatialDiffuse() 67 GModelSpatialDiffuse()
@@ -98,11 +100,11 @@ GModelSpatialDiffuseConst::GModelSpatialDiffuseConst(const GXmlElement&amp; xml) : @@ -98,11 +100,11 @@ GModelSpatialDiffuseConst::GModelSpatialDiffuseConst(const GXmlElement&amp; xml) :
98 /***********************************************************************//** 100 /***********************************************************************//**
99 * @brief Value constructor 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 GModelSpatialDiffuseConst::GModelSpatialDiffuseConst(const double& value) : 109 GModelSpatialDiffuseConst::GModelSpatialDiffuseConst(const double& value) :
108 GModelSpatialDiffuse() 110 GModelSpatialDiffuse()
@@ -125,6 +127,9 @@ GModelSpatialDiffuseConst::GModelSpatialDiffuseConst(const double&amp; value) : @@ -125,6 +127,9 @@ GModelSpatialDiffuseConst::GModelSpatialDiffuseConst(const double&amp; value) :
125 * @brief Copy constructor 127 * @brief Copy constructor
126 * 128 *
127 * @param[in] model Isotropic spatial model. 129 * @param[in] model Isotropic spatial model.
  130 + *
  131 + * Constructs isotropic spatial model by copying another isotropic spatial
  132 + * model.
128 ***************************************************************************/ 133 ***************************************************************************/
129 GModelSpatialDiffuseConst::GModelSpatialDiffuseConst(const GModelSpatialDiffuseConst& model) : 134 GModelSpatialDiffuseConst::GModelSpatialDiffuseConst(const GModelSpatialDiffuseConst& model) :
130 GModelSpatialDiffuse(model) 135 GModelSpatialDiffuse(model)
@@ -142,6 +147,8 @@ GModelSpatialDiffuseConst::GModelSpatialDiffuseConst(const GModelSpatialDiffuseC @@ -142,6 +147,8 @@ GModelSpatialDiffuseConst::GModelSpatialDiffuseConst(const GModelSpatialDiffuseC
142 147
143 /***********************************************************************//** 148 /***********************************************************************//**
144 * @brief Destructor 149 * @brief Destructor
  150 + *
  151 + * Destructs isotropic spatial model.
145 ***************************************************************************/ 152 ***************************************************************************/
146 GModelSpatialDiffuseConst::~GModelSpatialDiffuseConst(void) 153 GModelSpatialDiffuseConst::~GModelSpatialDiffuseConst(void)
147 { 154 {
@@ -164,6 +171,8 @@ GModelSpatialDiffuseConst::~GModelSpatialDiffuseConst(void) @@ -164,6 +171,8 @@ GModelSpatialDiffuseConst::~GModelSpatialDiffuseConst(void)
164 * 171 *
165 * @param[in] model Isotropic spatial model. 172 * @param[in] model Isotropic spatial model.
166 * @return Isotropic spatial model. 173 * @return Isotropic spatial model.
  174 + *
  175 + * Assigns an isotropic spatial model.
167 ***************************************************************************/ 176 ***************************************************************************/
168 GModelSpatialDiffuseConst& GModelSpatialDiffuseConst::operator=(const GModelSpatialDiffuseConst& model) 177 GModelSpatialDiffuseConst& GModelSpatialDiffuseConst::operator=(const GModelSpatialDiffuseConst& model)
169 { 178 {
@@ -197,10 +206,13 @@ GModelSpatialDiffuseConst&amp; GModelSpatialDiffuseConst::operator=(const GModelSpat @@ -197,10 +206,13 @@ GModelSpatialDiffuseConst&amp; GModelSpatialDiffuseConst::operator=(const GModelSpat
197 206
198 /***********************************************************************//** 207 /***********************************************************************//**
199 * @brief Clear isotropic spatial model 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 void GModelSpatialDiffuseConst::clear(void) 213 void GModelSpatialDiffuseConst::clear(void)
202 { 214 {
203 - // Free class members (base and derived classes, derived class first) 215 + // Free class members
204 free_members(); 216 free_members();
205 this->GModelSpatialDiffuse::free_members(); 217 this->GModelSpatialDiffuse::free_members();
206 this->GModelSpatial::free_members(); 218 this->GModelSpatial::free_members();
@@ -219,6 +231,8 @@ void GModelSpatialDiffuseConst::clear(void) @@ -219,6 +231,8 @@ void GModelSpatialDiffuseConst::clear(void)
219 * @brief Clone isotropic spatial model 231 * @brief Clone isotropic spatial model
220 * 232 *
221 * @return Pointer to deep copy of isotropic spatial model. 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 GModelSpatialDiffuseConst* GModelSpatialDiffuseConst::clone(void) const 237 GModelSpatialDiffuseConst* GModelSpatialDiffuseConst::clone(void) const
224 { 238 {
@@ -228,15 +242,22 @@ GModelSpatialDiffuseConst* GModelSpatialDiffuseConst::clone(void) const @@ -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 double GModelSpatialDiffuseConst::eval(const GPhoton& photon) const 262 double GModelSpatialDiffuseConst::eval(const GPhoton& photon) const
242 { 263 {
@@ -252,14 +273,32 @@ double GModelSpatialDiffuseConst::eval(const GPhoton&amp; photon) const @@ -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 double GModelSpatialDiffuseConst::eval_gradients(const GPhoton& photon) const 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,41 +322,91 @@ double GModelSpatialDiffuseConst::eval_gradients(const GPhoton&amp; photon) const
283 /***********************************************************************//** 322 /***********************************************************************//**
284 * @brief Return MC sky direction 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 * @param[in,out] ran Random number generator. 327 * @param[in,out] ran Random number generator.
289 * @return Sky direction. 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 GSkyDir GModelSpatialDiffuseConst::mc(const GEnergy& energy, 336 GSkyDir GModelSpatialDiffuseConst::mc(const GEnergy& energy,
295 const GTime& time, 337 const GTime& time,
296 GRan& ran) const 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 // Return sky direction 351 // Return sky direction
307 return dir; 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 * @brief Read model from XML element 406 * @brief Read model from XML element
313 * 407 *
314 * @param[in] xml XML element. 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 * Read the isotropic source model information from an XML element. The XML 410 * Read the isotropic source model information from an XML element. The XML
322 * element is expected to have the following format: 411 * element is expected to have the following format:
323 * 412 *
@@ -331,23 +420,11 @@ void GModelSpatialDiffuseConst::read(const GXmlElement&amp; xml) @@ -331,23 +420,11 @@ void GModelSpatialDiffuseConst::read(const GXmlElement&amp; xml)
331 // Clear model 420 // Clear model
332 clear(); 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 // Return 429 // Return
353 return; 430 return;
@@ -361,10 +438,6 @@ void GModelSpatialDiffuseConst::read(const GXmlElement&amp; xml) @@ -361,10 +438,6 @@ void GModelSpatialDiffuseConst::read(const GXmlElement&amp; xml)
361 * 438 *
362 * @exception GException::model_invalid_spatial 439 * @exception GException::model_invalid_spatial
363 * Existing XML element is not of type "ConstantValue" 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 * Write the isotropic source model information into an XML element. The XML 442 * Write the isotropic source model information into an XML element. The XML
370 * element will have the following format: 443 * element will have the following format:
@@ -387,28 +460,11 @@ void GModelSpatialDiffuseConst::write(GXmlElement&amp; xml) const @@ -387,28 +460,11 @@ void GModelSpatialDiffuseConst::write(GXmlElement&amp; xml) const
387 "Spatial model is not of type \"ConstantValue\"."); 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 // Return 469 // Return
414 return; 470 return;
@@ -467,6 +523,10 @@ void GModelSpatialDiffuseConst::init_members(void) @@ -467,6 +523,10 @@ void GModelSpatialDiffuseConst::init_members(void)
467 m_value.gradient(0.0); 523 m_value.gradient(0.0);
468 m_value.has_grad(true); 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 // Set parameter pointer(s) 530 // Set parameter pointer(s)
471 m_pars.clear(); 531 m_pars.clear();
472 m_pars.push_back(&m_value); 532 m_pars.push_back(&m_value);
@@ -484,7 +544,9 @@ void GModelSpatialDiffuseConst::init_members(void) @@ -484,7 +544,9 @@ void GModelSpatialDiffuseConst::init_members(void)
484 void GModelSpatialDiffuseConst::copy_members(const GModelSpatialDiffuseConst& model) 544 void GModelSpatialDiffuseConst::copy_members(const GModelSpatialDiffuseConst& model)
485 { 545 {
486 // Copy members 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 // Set parameter pointer(s) 551 // Set parameter pointer(s)
490 m_pars.clear(); 552 m_pars.clear();