Commit 5cbe4da0b2559b6d8c6a4b4bb0899608b689bca0
1 parent
0b7ec5a0
Add node manipulation methods.
A set of methods have been added for node manipulation, such as retrieval of node energy and intensity, but also appending, inserting and removing of nodes or extending the node function.
Showing
3 changed files
with
563 additions
and
176 deletions
include/GModelSpectralNodes.hpp
| ... | ... | @@ -43,22 +43,37 @@ |
| 43 | 43 | * @brief Spectral nodes model class |
| 44 | 44 | * |
| 45 | 45 | * This class implements a piecewise power law between spectral nodes |
| 46 | - * \f$(E_i, I_i)\f$, | |
| 46 | + * | |
| 47 | + * \f[ | |
| 48 | + * ({\tt m\_energies[i]}, {\tt m\_values[i]}) | |
| 49 | + * \f] | |
| 50 | + * | |
| 47 | 51 | * where |
| 48 | - * \f$E_i\f$ is the energy and \f$I_i\f$ is the intensity of node \f$i\f$. | |
| 49 | - * For a given energy \f$E\f$, the piecewise powerlaw is computing by | |
| 50 | - * finding the bracketing energies \f$E_1 <= E <= E_2\f$ and computing | |
| 51 | - * \f[I(E)=10^{(\log v_1 + \log s_1) w_1 + (\log v_2 + \log s_2) w_2}\f] | |
| 52 | + * - \f${\tt m\_energies[i]}\f$ is the energy, and | |
| 53 | + * - \f${\tt m\_values[i]}\f$ is the intensity (in photons/cm2/s/MeV) | |
| 54 | + * of node \f$i\f$. | |
| 55 | + * | |
| 56 | + * For a given energy \f$E\f$, the piecewise power law is computing by | |
| 57 | + * finding the bracketing energies | |
| 58 | + * \f${\tt m\_energies[i]} <= E <= {\tt m\_energies[i+1]}\f$ and computing | |
| 59 | + * | |
| 60 | + * \f[ | |
| 61 | + * S_{\rm E}(E | t) = | |
| 62 | + * 10^{(\log {\tt m\_values[i]}) w_{i} + | |
| 63 | + * (\log {\tt m\_values[i+1]}) w_{i+1}} | |
| 64 | + * \f] | |
| 65 | + * | |
| 52 | 66 | * where |
| 53 | - * \f$I_1 = v_1 s_1\f$ is the intensity of node 1 (\f$E_1\f$), | |
| 54 | - * \f$I_2 = v_2 s_2\f$ is the intensity of node 2 (\f$E_2\f$), | |
| 55 | - * \f$w_1\f$ is the weighting of node 1, and | |
| 56 | - * \f$w_2\f$ is the weighting of node 2. | |
| 57 | - * The weightings \f$w_1\f$ and \f$w_2\f$ are computed by linear | |
| 67 | + * - \f${\tt m\_values[i]}\f$ is the intensity of node \f$i\f$, | |
| 68 | + * - \f${\tt m\_values[i+1]}\f$ is the intensity of node \f$i+1\f$, | |
| 69 | + * - \f$w_{i}\f$ is the weighting of node \f$i\f$, and | |
| 70 | + * - \f$w_{i+1}\f$ is the weighting of node \f$i+1\f$. | |
| 71 | + * | |
| 72 | + * The weightings \f$w_{i}\f$ and \f$w_{i+1}\f$ are computed by linear | |
| 58 | 73 | * interpolation (in the log-log plane) between the nodes |
| 59 | - * \f$(\log E_1, \log I_1)\f$ | |
| 74 | + * \f$(\log {\tt m\_energies[i]}, \log{\tt m\_values[i]})\f$ | |
| 60 | 75 | * and |
| 61 | - * \f$(\log E_2, \log I_2)\f$ | |
| 76 | + * \f$(\log {\tt m\_energies[i+1]}, \log{\tt m\_values[i+1]})\f$ | |
| 62 | 77 | * to the requested energy \f$\log E\f$. |
| 63 | 78 | ***************************************************************************/ |
| 64 | 79 | class GModelSpectralNodes : public GModelSpectral { |
| ... | ... | @@ -73,7 +88,7 @@ public: |
| 73 | 88 | // Operators |
| 74 | 89 | virtual GModelSpectralNodes& operator=(const GModelSpectralNodes& model); |
| 75 | 90 | |
| 76 | - // Implemented pure virtual methods | |
| 91 | + // Implemented pure virtual base class methods | |
| 77 | 92 | virtual void clear(void); |
| 78 | 93 | virtual GModelSpectralNodes* clone(void) const; |
| 79 | 94 | virtual std::string type(void) const; |
| ... | ... | @@ -93,6 +108,19 @@ public: |
| 93 | 108 | virtual void write(GXmlElement& xml) const; |
| 94 | 109 | virtual std::string print(void) const; |
| 95 | 110 | |
| 111 | + // Other methods | |
| 112 | + int nodes(void) const; | |
| 113 | + void append(const GEnergy& energy, const double& intensity); | |
| 114 | + void insert(const int& index, const GEnergy& energy, | |
| 115 | + const double& intensity); | |
| 116 | + void remove(const int& index); | |
| 117 | + void reserve(const int& num); | |
| 118 | + void extend(const GModelSpectralNodes& nodes); | |
| 119 | + GEnergy energy(const int& index) const; | |
| 120 | + void energy(const int& index, const GEnergy& energy); | |
| 121 | + double intensity(const int& index) const; | |
| 122 | + void intensity(const int& index, const double& intensity); | |
| 123 | + | |
| 96 | 124 | protected: |
| 97 | 125 | // Protected methods |
| 98 | 126 | void init_members(void); |
| ... | ... | @@ -149,4 +177,18 @@ std::string GModelSpectralNodes::type(void) const |
| 149 | 177 | return "NodeFunction"; |
| 150 | 178 | } |
| 151 | 179 | |
| 180 | + | |
| 181 | +/***********************************************************************//** | |
| 182 | + * @brief Return number of nodes | |
| 183 | + * | |
| 184 | + * @return Number of nodes. | |
| 185 | + * | |
| 186 | + * Returns the number of nodes in the node function model. | |
| 187 | + ***************************************************************************/ | |
| 188 | +inline | |
| 189 | +int GModelSpectralNodes::nodes(void) const | |
| 190 | +{ | |
| 191 | + return (m_energies.size()); | |
| 192 | +} | |
| 193 | + | |
| 152 | 194 | #endif /* GMODELSPECTRALNODES_HPP */ | ... | ... |
pyext/GModelSpectralNodes.i
| ... | ... | @@ -61,6 +61,19 @@ public: |
| 61 | 61 | GRan& ran) const; |
| 62 | 62 | virtual void read(const GXmlElement& xml); |
| 63 | 63 | virtual void write(GXmlElement& xml) const; |
| 64 | + | |
| 65 | + // Other methods | |
| 66 | + int nodes(void) const; | |
| 67 | + void append(const GEnergy& energy, const double& intensity); | |
| 68 | + void insert(const int& index, const GEnergy& energy, | |
| 69 | + const double& intensity); | |
| 70 | + void remove(const int& index); | |
| 71 | + void reserve(const int& num); | |
| 72 | + void extend(const GModelSpectralNodes& nodes); | |
| 73 | + GEnergy energy(const int& index) const; | |
| 74 | + void energy(const int& index, const GEnergy& energy); | |
| 75 | + double intensity(const int& index) const; | |
| 76 | + void intensity(const int& index, const double& intensity); | |
| 64 | 77 | }; |
| 65 | 78 | |
| 66 | 79 | ... | ... |
src/model/GModelSpectralNodes.cpp
| ... | ... | @@ -43,9 +43,15 @@ const GModelSpectralRegistry g_spectral_nodes_registry(&g_spectral_nodes_seed); |
| 43 | 43 | /* __ Method name definitions ____________________________________________ */ |
| 44 | 44 | #define G_FLUX "GModelSpectralNodes::flux(GEnergy&, GEnergy&)" |
| 45 | 45 | #define G_EFLUX "GModelSpectralNodes::eflux(GEnergy&, GEnergy&)" |
| 46 | -#define G_MC "GModelSpectralNodes::mc(GEnergy&, GEnergy&, GRan&)" | |
| 46 | +#define G_MC "GModelSpectralNodes::mc(GEnergy&, GEnergy&, GTime&, GRan&)" | |
| 47 | 47 | #define G_READ "GModelSpectralNodes::read(GXmlElement&)" |
| 48 | 48 | #define G_WRITE "GModelSpectralNodes::write(GXmlElement&)" |
| 49 | +#define G_INSERT "GModelSpectralNodes::insert(int&, GEnergy&, double&)" | |
| 50 | +#define G_REMOVE "GModelSpectralNodes::remove(int&)" | |
| 51 | +#define G_ENERGY_GET "GModelSpectralNodes::energy(int&)" | |
| 52 | +#define G_ENERGY_SET "GModelSpectralNodes::energy(int&, GEnergy&)" | |
| 53 | +#define G_INTENSITY_GET "GModelSpectralNodes::intensity(int&)" | |
| 54 | +#define G_INTENSITY_SET "GModelSpectralNodes::intensity(int&, double&)" | |
| 49 | 55 | |
| 50 | 56 | /* __ Macros _____________________________________________________________ */ |
| 51 | 57 | |
| ... | ... | @@ -78,12 +84,12 @@ GModelSpectralNodes::GModelSpectralNodes(void) : GModelSpectral() |
| 78 | 84 | * |
| 79 | 85 | * @param[in] xml XML element. |
| 80 | 86 | * |
| 81 | - * Creates instance of a spectral nodes model by extracting information from | |
| 82 | - * an XML element. See GModelSpectralNodes::read() for more information about | |
| 83 | - * the expected structure of the XML element. | |
| 87 | + * Construct spectral nodes model by extracting information from an XML | |
| 88 | + * element. See the read() method for more information about the expected | |
| 89 | + * structure of the XML element. | |
| 84 | 90 | ***************************************************************************/ |
| 85 | -GModelSpectralNodes::GModelSpectralNodes(const GXmlElement& xml) | |
| 86 | - : GModelSpectral() | |
| 91 | +GModelSpectralNodes::GModelSpectralNodes(const GXmlElement& xml) : | |
| 92 | + GModelSpectral() | |
| 87 | 93 | { |
| 88 | 94 | // Initialise members |
| 89 | 95 | init_members(); |
| ... | ... | @@ -101,8 +107,8 @@ GModelSpectralNodes::GModelSpectralNodes(const GXmlElement& xml) |
| 101 | 107 | * |
| 102 | 108 | * @param[in] model Spectral nodes model. |
| 103 | 109 | ***************************************************************************/ |
| 104 | -GModelSpectralNodes::GModelSpectralNodes(const GModelSpectralNodes& model) | |
| 105 | - : GModelSpectral(model) | |
| 110 | +GModelSpectralNodes::GModelSpectralNodes(const GModelSpectralNodes& model) : | |
| 111 | + GModelSpectral(model) | |
| 106 | 112 | { |
| 107 | 113 | // Initialise members |
| 108 | 114 | init_members(); |
| ... | ... | @@ -138,8 +144,9 @@ GModelSpectralNodes::~GModelSpectralNodes(void) |
| 138 | 144 | * @brief Assignment operator |
| 139 | 145 | * |
| 140 | 146 | * @param[in] model Spectral nodes model. |
| 147 | + * @return Spectral nodes model. | |
| 141 | 148 | ***************************************************************************/ |
| 142 | -GModelSpectralNodes& GModelSpectralNodes::operator= (const GModelSpectralNodes& model) | |
| 149 | +GModelSpectralNodes& GModelSpectralNodes::operator=(const GModelSpectralNodes& model) | |
| 143 | 150 | { |
| 144 | 151 | // Execute only if object is not identical |
| 145 | 152 | if (this != &model) { |
| ... | ... | @@ -170,7 +177,7 @@ GModelSpectralNodes& GModelSpectralNodes::operator= (const GModelSpectralNodes& |
| 170 | 177 | ==========================================================================*/ |
| 171 | 178 | |
| 172 | 179 | /***********************************************************************//** |
| 173 | - * @brief Clear instance | |
| 180 | + * @brief Clear spectral nodes model | |
| 174 | 181 | ***************************************************************************/ |
| 175 | 182 | void GModelSpectralNodes::clear(void) |
| 176 | 183 | { |
| ... | ... | @@ -188,10 +195,11 @@ void GModelSpectralNodes::clear(void) |
| 188 | 195 | |
| 189 | 196 | |
| 190 | 197 | /***********************************************************************//** |
| 191 | - * @brief Clone instance | |
| 198 | + * @brief Clone spectral nodes model | |
| 192 | 199 | ***************************************************************************/ |
| 193 | 200 | GModelSpectralNodes* GModelSpectralNodes::clone(void) const |
| 194 | 201 | { |
| 202 | + // Clone spectral nodes model | |
| 195 | 203 | return new GModelSpectralNodes(*this); |
| 196 | 204 | } |
| 197 | 205 | |
| ... | ... | @@ -203,23 +211,26 @@ GModelSpectralNodes* GModelSpectralNodes::clone(void) const |
| 203 | 211 | * @param[in] srcTime True photon arrival time. |
| 204 | 212 | * @return Model value (ph/cm2/s/MeV). |
| 205 | 213 | * |
| 206 | - * The spectral model is defined as a piecewise power law between spectral | |
| 207 | - * nodes \f$(E_i, I_i)\f$, | |
| 208 | - * where | |
| 209 | - * \f$E_i\f$ is the energy and \f$I_i\f$ is the intensity of node \f$i\f$. | |
| 210 | - * For a given energy \f$E\f$, the piecewise powerlaw is computing by | |
| 211 | - * finding the bracketing energies \f$E_1 <= E <= E_2\f$ and computing | |
| 212 | - * \f[I(E)=10^{(\log v_1 + \log s_1) w_1 + (\log v_2 + \log s_2) w_2}\f] | |
| 214 | + * Computes | |
| 215 | + * | |
| 216 | + * \f[ | |
| 217 | + * S_{\rm E}(E | t) = | |
| 218 | + * 10^{(\log {\tt m\_values[i]}) w_{i} + | |
| 219 | + * (\log {\tt m\_values[i+1]}) w_{i+1}} | |
| 220 | + * \f] | |
| 221 | + * | |
| 213 | 222 | * where |
| 214 | - * \f$I_1 = v_1 s_1\f$ is the intensity of node 1 (\f$E_1\f$), | |
| 215 | - * \f$I_2 = v_2 s_2\f$ is the intensity of node 2 (\f$E_2\f$), | |
| 216 | - * \f$w_1\f$ is the weighting of node 1, and | |
| 217 | - * \f$w_2\f$ is the weighting of node 2. | |
| 218 | - * The weightings \f$w_1\f$ and \f$w_2\f$ are computed by linear | |
| 223 | + * - \f${\tt m\_values[i]}\f$ is the intensity of node \f$i\f$, | |
| 224 | + * - \f${\tt m\_values[i+1]}\f$ is the intensity of node \f$i+1\f$, | |
| 225 | + * - \f$w_{i}\f$ is the weighting of node \f$i\f$, | |
| 226 | + * - \f$w_{i+1}\f$ is the weighting of node \f$i+1\f$, and | |
| 227 | + * - \f${\tt m\_energies[i]} <= E <= {\tt m\_energies[i+1]}\f$. | |
| 228 | + * | |
| 229 | + * The weightings \f$w_{i}\f$ and \f$w_{i+1}\f$ are computed by linear | |
| 219 | 230 | * interpolation (in the log-log plane) between the nodes |
| 220 | - * \f$(\log E_1, \log I_1)\f$ | |
| 231 | + * \f$(\log {\tt m\_energies[i]}, \log{\tt m\_values[i]})\f$ | |
| 221 | 232 | * and |
| 222 | - * \f$(\log E_2, \log I_2)\f$ | |
| 233 | + * \f$(\log {\tt m\_energies[i+1]}, \log{\tt m\_values[i+1]})\f$ | |
| 223 | 234 | * to the requested energy \f$\log E\f$. |
| 224 | 235 | ***************************************************************************/ |
| 225 | 236 | double GModelSpectralNodes::eval(const GEnergy& srcEng, |
| ... | ... | @@ -237,7 +248,8 @@ double GModelSpectralNodes::eval(const GEnergy& srcEng, |
| 237 | 248 | #if defined(G_NAN_CHECK) |
| 238 | 249 | if (isnotanumber(value) || isinfinite(value)) { |
| 239 | 250 | std::cout << "*** ERROR: GModelSpectralNodes::eval"; |
| 240 | - std::cout << "(srcEng=" << srcEng << "):"; | |
| 251 | + std::cout << "(srcEng=" << srcEng; | |
| 252 | + std::cout << ", srcTime=" << srcTime << "):"; | |
| 241 | 253 | std::cout << " NaN/Inf encountered"; |
| 242 | 254 | std::cout << " (value=" << value; |
| 243 | 255 | std::cout << ", exponent=" << exponent; |
| ... | ... | @@ -257,28 +269,35 @@ double GModelSpectralNodes::eval(const GEnergy& srcEng, |
| 257 | 269 | * @param[in] srcTime True photon arrival time. |
| 258 | 270 | * @return Model value (ph/cm2/s/MeV). |
| 259 | 271 | * |
| 260 | - * The spectral model is defined as a piecewise power law between spectral | |
| 261 | - * nodes \f$(E_i, I_i)\f$, | |
| 262 | - * where | |
| 263 | - * \f$E_i\f$ is the energy and \f$I_i\f$ is the intensity of node \f$i\f$. | |
| 264 | - * For a given energy \f$E\f$, the piecewise powerlaw is computing by | |
| 265 | - * finding the bracketing energies \f$E_1 <= E <= E_2\f$ and computing | |
| 266 | - * \f[I(E)=10^{(\log v_1 + \log s_1) w_1 + (\log v_2 + \log s_2) w_2}\f] | |
| 272 | + * Computes | |
| 273 | + * | |
| 274 | + * \f[ | |
| 275 | + * S_{\rm E}(E | t) = | |
| 276 | + * 10^{(\log {\tt m\_values[i]}) w_{i} + | |
| 277 | + * (\log {\tt m\_values[i+1]}) w_{i+1}} | |
| 278 | + * \f] | |
| 279 | + * | |
| 267 | 280 | * where |
| 268 | - * \f$I_1 = v_1 s_1\f$ is the intensity of node 1 (\f$E_1\f$), | |
| 269 | - * \f$I_2 = v_2 s_2\f$ is the intensity of node 2 (\f$E_2\f$), | |
| 270 | - * \f$w_1\f$ is the weighting of node 1, and | |
| 271 | - * \f$w_2\f$ is the weighting of node 2. | |
| 272 | - * The weightings \f$w_1\f$ and \f$w_2\f$ are computed by linear | |
| 281 | + * - \f${\tt m\_values[i]}\f$ is the intensity of node \f$i\f$, | |
| 282 | + * - \f${\tt m\_values[i+1]}\f$ is the intensity of node \f$i+1\f$, | |
| 283 | + * - \f$w_{i}\f$ is the weighting of node \f$i\f$, | |
| 284 | + * - \f$w_{i+1}\f$ is the weighting of node \f$i+1\f$, and | |
| 285 | + * - \f${\tt m\_energies[i]} <= E <= {\tt m\_energies[i+1]}\f$. | |
| 286 | + * | |
| 287 | + * The weightings \f$w_{i}\f$ and \f$w_{i+1}\f$ are computed by linear | |
| 273 | 288 | * interpolation (in the log-log plane) between the nodes |
| 274 | - * \f$(\log E_1, \log I_1)\f$ | |
| 289 | + * \f$(\log {\tt m\_energies[i]}, \log{\tt m\_values[i]})\f$ | |
| 275 | 290 | * and |
| 276 | - * \f$(\log E_2, \log I_2)\f$ | |
| 291 | + * \f$(\log {\tt m\_energies[i+1]}, \log{\tt m\_values[i+1]})\f$ | |
| 277 | 292 | * to the requested energy \f$\log E\f$. |
| 278 | 293 | * |
| 279 | - * The partial derivatives are given by | |
| 280 | - * \f[dI/dv_i=I(E) w_i / v_i\f] | |
| 281 | - * for \f$i=1,2\f$ and \f$0\f$ for all other nodes. | |
| 294 | + * The method also evaluates the partial derivatives of the model with | |
| 295 | + * respect to the parameters using | |
| 296 | + * | |
| 297 | + * \f[ | |
| 298 | + * \frac{\delta S_{\rm E}(E | t)}{\delta {\tt m\_values[i]}} = | |
| 299 | + * \frac{S_{\rm E}(E | t) \, w_i}{{\tt m\_values[i]}} | |
| 300 | + * \f] | |
| 282 | 301 | ***************************************************************************/ |
| 283 | 302 | double GModelSpectralNodes::eval_gradients(const GEnergy& srcEng, |
| 284 | 303 | const GTime& srcTime) |
| ... | ... | @@ -304,26 +323,27 @@ double GModelSpectralNodes::eval_gradients(const GEnergy& srcEng, |
| 304 | 323 | |
| 305 | 324 | // Initialise gradients |
| 306 | 325 | for (int i = 0; i < m_values.size(); ++i) { |
| 307 | - const_cast<GModelSpectralNodes*>(this)->m_values[i].factor_gradient(0.0); | |
| 326 | + m_values[i].factor_gradient(0.0); | |
| 308 | 327 | } |
| 309 | 328 | |
| 310 | 329 | // Gradient for left node |
| 311 | 330 | if (m_values[inx_left].isfree()) { |
| 312 | 331 | double grad = value * wgt_left / m_values[inx_left].factor_value(); |
| 313 | - const_cast<GModelSpectralNodes*>(this)->m_values[inx_left].factor_gradient(grad); | |
| 332 | + m_values[inx_left].factor_gradient(grad); | |
| 314 | 333 | } |
| 315 | 334 | |
| 316 | 335 | // Gradient for right node |
| 317 | 336 | if (m_values[inx_right].isfree()) { |
| 318 | 337 | double grad = value * wgt_right / m_values[inx_right].factor_value(); |
| 319 | - const_cast<GModelSpectralNodes*>(this)->m_values[inx_right].factor_gradient(grad); | |
| 338 | + m_values[inx_right].factor_gradient(grad); | |
| 320 | 339 | } |
| 321 | 340 | |
| 322 | 341 | // Compile option: Check for NaN/Inf |
| 323 | 342 | #if defined(G_NAN_CHECK) |
| 324 | 343 | if (isnotanumber(value) || isinfinite(value)) { |
| 325 | 344 | std::cout << "*** ERROR: GModelSpectralNodes::eval_gradients"; |
| 326 | - std::cout << "(srcEng=" << srcEng << "):"; | |
| 345 | + std::cout << "(srcEng=" << srcEng; | |
| 346 | + std::cout << ", srcTime=" << srcTime << "):"; | |
| 327 | 347 | std::cout << " NaN/Inf encountered"; |
| 328 | 348 | std::cout << " (value=" << value; |
| 329 | 349 | std::cout << ", exponent=" << exponent; |
| ... | ... | @@ -343,37 +363,30 @@ double GModelSpectralNodes::eval_gradients(const GEnergy& srcEng, |
| 343 | 363 | * @param[in] emax Maximum photon energy. |
| 344 | 364 | * @return Photon flux (ph/cm2/s). |
| 345 | 365 | * |
| 346 | - * @exception GException::erange_invalid | |
| 347 | - * Energy range is invalid (emin < emax required). | |
| 348 | - * | |
| 349 | 366 | * Computes |
| 350 | - * \f[\int_{E_{\rm min}}^{E_{\rm max}} I(E) dE\f] | |
| 367 | + * | |
| 368 | + * \f[ | |
| 369 | + * \int_{\tt emin}^{\tt emax} S_{\rm E}(E | t) dE | |
| 370 | + * \f] | |
| 371 | + * | |
| 351 | 372 | * where |
| 352 | - * \f$E_{\rm min}\f$ and \f$E_{\rm max}\f$ are the minimum and maximum | |
| 353 | - * energy, respectively, and | |
| 354 | - * \f$I(E)\f$ is the spectral model (units: ph/cm2/s/MeV). | |
| 373 | + * - [@p emin, @p emax] is an energy interval, and | |
| 374 | + * - \f$S_{\rm E}(E | t)\f$ is the spectral model (ph/cm2/s/MeV). | |
| 355 | 375 | ***************************************************************************/ |
| 356 | 376 | double GModelSpectralNodes::flux(const GEnergy& emin, const GEnergy& emax) const |
| 357 | 377 | { |
| 358 | - // Throw an exception if energy range is invalid | |
| 359 | - if (emin >= emax) { | |
| 360 | - throw GException::erange_invalid(G_FLUX, emin.MeV(), emax.MeV(), | |
| 361 | - "Minimum energy < maximum energy required."); | |
| 362 | - | |
| 363 | - } | |
| 364 | - | |
| 365 | - // Update flux cache | |
| 366 | - update_flux_cache(); | |
| 367 | - | |
| 368 | 378 | // Initialise flux |
| 369 | 379 | double flux = 0.0; |
| 370 | 380 | |
| 371 | - // Get energy range in MeV | |
| 372 | - double e_min = emin.MeV(); | |
| 373 | - double e_max = emax.MeV(); | |
| 374 | - | |
| 375 | - // Continue only if e_max > e_min | |
| 376 | - if (e_max > e_min) { | |
| 381 | + // Compute only if integration range is valid | |
| 382 | + if (emin < emax) { | |
| 383 | + | |
| 384 | + // Update flux cache | |
| 385 | + update_flux_cache(); | |
| 386 | + | |
| 387 | + // Get energy range in MeV | |
| 388 | + double e_min = emin.MeV(); | |
| 389 | + double e_max = emax.MeV(); | |
| 377 | 390 | |
| 378 | 391 | // Determine left node index for minimum energy |
| 379 | 392 | m_lin_energies.set_value(e_min); |
| ... | ... | @@ -421,10 +434,9 @@ double GModelSpectralNodes::flux(const GEnergy& emin, const GEnergy& emax) const |
| 421 | 434 | e_max, |
| 422 | 435 | m_epivot[inx_emax], |
| 423 | 436 | m_gamma[inx_emax]); |
| 424 | - | |
| 425 | - } // endelse: emin and emax not between same nodes | |
| 426 | - | |
| 427 | - } // endif: e_max > e_min | |
| 437 | + } | |
| 438 | + | |
| 439 | + } // endif: integration range was valid | |
| 428 | 440 | |
| 429 | 441 | // Return |
| 430 | 442 | return flux; |
| ... | ... | @@ -438,37 +450,30 @@ double GModelSpectralNodes::flux(const GEnergy& emin, const GEnergy& emax) const |
| 438 | 450 | * @param[in] emax Maximum photon energy. |
| 439 | 451 | * @return Energy flux (erg/cm2/s). |
| 440 | 452 | * |
| 441 | - * @exception GException::erange_invalid | |
| 442 | - * Energy range is invalid (emin < emax required). | |
| 443 | - * | |
| 444 | 453 | * Computes |
| 445 | - * \f[\int_{E_{\rm min}}^{E_{\rm max}} I(E) E dE\f] | |
| 454 | + * | |
| 455 | + * \f[ | |
| 456 | + * \int_{\tt emin}^{\tt emax} S_{\rm E}(E | t) E \, dE | |
| 457 | + * \f] | |
| 458 | + * | |
| 446 | 459 | * where |
| 447 | - * \f$E_{\rm min}\f$ and \f$E_{\rm max}\f$ are the minimum and maximum | |
| 448 | - * energy, respectively, and | |
| 449 | - * \f$I(E)\f$ is the spectral model (units: ph/cm2/s/MeV). | |
| 460 | + * - [@p emin, @p emax] is an energy interval, and | |
| 461 | + * - \f$S_{\rm E}(E | t)\f$ is the spectral model (ph/cm2/s/MeV). | |
| 450 | 462 | ***************************************************************************/ |
| 451 | 463 | double GModelSpectralNodes::eflux(const GEnergy& emin, const GEnergy& emax) const |
| 452 | 464 | { |
| 453 | - // Throw an exception if energy range is invalid | |
| 454 | - if (emin >= emax) { | |
| 455 | - throw GException::erange_invalid(G_EFLUX, emin.MeV(), emax.MeV(), | |
| 456 | - "Minimum energy < maximum energy required."); | |
| 457 | - | |
| 458 | - } | |
| 459 | - | |
| 460 | - // Update flux cache | |
| 461 | - update_flux_cache(); | |
| 462 | - | |
| 463 | 465 | // Initialise flux |
| 464 | - double flux = 0.0; | |
| 466 | + double eflux = 0.0; | |
| 465 | 467 | |
| 466 | - // Get energy range in MeV | |
| 467 | - double e_min = emin.MeV(); | |
| 468 | - double e_max = emax.MeV(); | |
| 468 | + // Compute only if integration range is valid | |
| 469 | + if (emin < emax) { | |
| 470 | + | |
| 471 | + // Update flux cache | |
| 472 | + update_flux_cache(); | |
| 469 | 473 | |
| 470 | - // Continue only if e_max > e_min | |
| 471 | - if (e_max > e_min) { | |
| 474 | + // Get energy range in MeV | |
| 475 | + double e_min = emin.MeV(); | |
| 476 | + double e_max = emax.MeV(); | |
| 472 | 477 | |
| 473 | 478 | // Determine left node index for minimum energy |
| 474 | 479 | m_lin_energies.set_value(e_min); |
| ... | ... | @@ -482,11 +487,11 @@ double GModelSpectralNodes::eflux(const GEnergy& emin, const GEnergy& emax) cons |
| 482 | 487 | // integrate over the energy interval using the appropriate power |
| 483 | 488 | // law parameters |
| 484 | 489 | if (inx_emin == inx_emax) { |
| 485 | - flux = m_prefactor[inx_emin] * | |
| 486 | - plaw_energy_flux(e_min, | |
| 487 | - e_max, | |
| 488 | - m_epivot[inx_emin], | |
| 489 | - m_gamma[inx_emin]) * MeV2erg; | |
| 490 | + eflux = m_prefactor[inx_emin] * | |
| 491 | + plaw_energy_flux(e_min, | |
| 492 | + e_max, | |
| 493 | + m_epivot[inx_emin], | |
| 494 | + m_gamma[inx_emin]) * MeV2erg; | |
| 490 | 495 | } |
| 491 | 496 | |
| 492 | 497 | // ... otherwise integrate over the nodes where emin and emax |
| ... | ... | @@ -499,30 +504,30 @@ double GModelSpectralNodes::eflux(const GEnergy& emin, const GEnergy& emax) cons |
| 499 | 504 | int i_start = (e_min < m_lin_energies[0]) ? inx_emin : inx_emin+1; |
| 500 | 505 | |
| 501 | 506 | // Integrate from emin to the node boundary |
| 502 | - flux = m_prefactor[inx_emin] * | |
| 503 | - plaw_energy_flux(e_min, | |
| 504 | - m_lin_energies[i_start], | |
| 505 | - m_epivot[inx_emin], | |
| 506 | - m_gamma[inx_emin]) * MeV2erg; | |
| 507 | + eflux = m_prefactor[inx_emin] * | |
| 508 | + plaw_energy_flux(e_min, | |
| 509 | + m_lin_energies[i_start], | |
| 510 | + m_epivot[inx_emin], | |
| 511 | + m_gamma[inx_emin]) * MeV2erg; | |
| 507 | 512 | |
| 508 | 513 | // Integrate over all nodes between |
| 509 | 514 | for (int i = i_start; i < inx_emax; ++i) { |
| 510 | - flux += m_eflux[i]; | |
| 515 | + eflux += m_eflux[i]; | |
| 511 | 516 | } |
| 512 | 517 | |
| 513 | 518 | // Integrate from node boundary to emax |
| 514 | - flux += m_prefactor[inx_emax] * | |
| 515 | - plaw_energy_flux(m_lin_energies[inx_emax], | |
| 516 | - e_max, | |
| 517 | - m_epivot[inx_emax], | |
| 518 | - m_gamma[inx_emax]) * MeV2erg; | |
| 519 | + eflux += m_prefactor[inx_emax] * | |
| 520 | + plaw_energy_flux(m_lin_energies[inx_emax], | |
| 521 | + e_max, | |
| 522 | + m_epivot[inx_emax], | |
| 523 | + m_gamma[inx_emax]) * MeV2erg; | |
| 519 | 524 | |
| 520 | 525 | } // endelse: emin and emax not between same nodes |
| 521 | 526 | |
| 522 | - } // endif: e_max > e_min | |
| 527 | + } // endif: integration range was valid | |
| 523 | 528 | |
| 524 | - // Return | |
| 525 | - return flux; | |
| 529 | + // Return flux | |
| 530 | + return eflux; | |
| 526 | 531 | } |
| 527 | 532 | |
| 528 | 533 | |
| ... | ... | @@ -537,6 +542,8 @@ double GModelSpectralNodes::eflux(const GEnergy& emin, const GEnergy& emax) cons |
| 537 | 542 | * |
| 538 | 543 | * @exception GException::erange_invalid |
| 539 | 544 | * Energy range is invalid (emin < emax required). |
| 545 | + * | |
| 546 | + * Returns Monte Carlo energy by randomly drawing from node function. | |
| 540 | 547 | ***************************************************************************/ |
| 541 | 548 | GEnergy GModelSpectralNodes::mc(const GEnergy& emin, |
| 542 | 549 | const GEnergy& emax, |
| ... | ... | @@ -552,41 +559,36 @@ GEnergy GModelSpectralNodes::mc(const GEnergy& emin, |
| 552 | 559 | // Allocate energy |
| 553 | 560 | GEnergy energy; |
| 554 | 561 | |
| 555 | - // Continue only if emax > emin | |
| 556 | - if (emax > emin) { | |
| 557 | - | |
| 558 | - // Update cache | |
| 559 | - mc_update(emin, emax); | |
| 560 | - | |
| 561 | - // Determine in which bin we reside | |
| 562 | - int inx = 0; | |
| 563 | - if (m_mc_cum.size() > 1) { | |
| 564 | - double u = ran.uniform(); | |
| 565 | - for (inx = m_mc_cum.size()-1; inx > 0; --inx) { | |
| 566 | - if (m_mc_cum[inx-1] <= u) | |
| 567 | - break; | |
| 568 | - } | |
| 569 | - } | |
| 570 | - | |
| 571 | - // Get random energy for specific bin | |
| 572 | - if (m_mc_exp[inx] != 0.0) { | |
| 573 | - double e_min = m_mc_min[inx]; | |
| 574 | - double e_max = m_mc_max[inx]; | |
| 575 | - double u = ran.uniform(); | |
| 576 | - double eng = (u > 0.0) | |
| 577 | - ? std::exp(std::log(u * (e_max - e_min) + e_min) / m_mc_exp[inx]) | |
| 578 | - : 0.0; | |
| 579 | - energy.MeV(eng); | |
| 580 | - } | |
| 581 | - else { | |
| 582 | - double e_min = m_mc_min[inx]; | |
| 583 | - double e_max = m_mc_max[inx]; | |
| 584 | - double u = ran.uniform(); | |
| 585 | - double eng = std::exp(u * (e_max - e_min) + e_min); | |
| 586 | - energy.MeV(eng); | |
| 562 | + // Update cache | |
| 563 | + mc_update(emin, emax); | |
| 564 | + | |
| 565 | + // Determine in which bin we reside | |
| 566 | + int inx = 0; | |
| 567 | + if (m_mc_cum.size() > 1) { | |
| 568 | + double u = ran.uniform(); | |
| 569 | + for (inx = m_mc_cum.size()-1; inx > 0; --inx) { | |
| 570 | + if (m_mc_cum[inx-1] <= u) | |
| 571 | + break; | |
| 587 | 572 | } |
| 573 | + } | |
| 588 | 574 | |
| 589 | - } // endif: emax > emin | |
| 575 | + // Get random energy for specific bin | |
| 576 | + if (m_mc_exp[inx] != 0.0) { | |
| 577 | + double e_min = m_mc_min[inx]; | |
| 578 | + double e_max = m_mc_max[inx]; | |
| 579 | + double u = ran.uniform(); | |
| 580 | + double eng = (u > 0.0) | |
| 581 | + ? std::exp(std::log(u * (e_max - e_min) + e_min) / m_mc_exp[inx]) | |
| 582 | + : 0.0; | |
| 583 | + energy.MeV(eng); | |
| 584 | + } | |
| 585 | + else { | |
| 586 | + double e_min = m_mc_min[inx]; | |
| 587 | + double e_max = m_mc_max[inx]; | |
| 588 | + double u = ran.uniform(); | |
| 589 | + double eng = std::exp(u * (e_max - e_min) + e_min); | |
| 590 | + energy.MeV(eng); | |
| 591 | + } | |
| 590 | 592 | |
| 591 | 593 | // Return energy |
| 592 | 594 | return energy; |
| ... | ... | @@ -603,9 +605,20 @@ GEnergy GModelSpectralNodes::mc(const GEnergy& emin, |
| 603 | 605 | * @exception GException::model_invalid_parnames |
| 604 | 606 | * Invalid model parameter name found in XML element. |
| 605 | 607 | * |
| 606 | - * Read the node function information from an XML element. The XML | |
| 607 | - * element is required to have at least two nodes. Each node has two | |
| 608 | - * parameters named "Energy" and "Intensity". | |
| 608 | + * Reads the spectral information from an XML element. The format of the XML | |
| 609 | + * elements is | |
| 610 | + * | |
| 611 | + * <spectrum type="NodeFunction"> | |
| 612 | + * <node> | |
| 613 | + * <parameter name="Energy" scale=".." value=".." min=".." max=".." free=".."/> | |
| 614 | + * <parameter name="Intensity" scale=".." value=".." min=".." max=".." free=".."/> | |
| 615 | + * </node> | |
| 616 | + * ... | |
| 617 | + * <node> | |
| 618 | + * <parameter name="Energy" scale=".." value=".." min=".." max=".." free=".."/> | |
| 619 | + * <parameter name="Intensity" scale=".." value=".." min=".." max=".." free=".."/> | |
| 620 | + * </node> | |
| 621 | + * </spectrum> | |
| 609 | 622 | * |
| 610 | 623 | * @todo Check that all energies and intensities are positive |
| 611 | 624 | * @todo Check that nodes are ordered |
| ... | ... | @@ -713,9 +726,20 @@ void GModelSpectralNodes::read(const GXmlElement& xml) |
| 713 | 726 | * @exception GException::model_invalid_parnames |
| 714 | 727 | * Invalid model parameter names found in XML element. |
| 715 | 728 | * |
| 716 | - * Write the node function information into an XML element. The XML element | |
| 717 | - * will have node leaves, where each node leave has two parameters named | |
| 718 | - * "Energy" and "Intensity". | |
| 729 | + * Writes the spectral information into an XML element. The format of the XML | |
| 730 | + * element is | |
| 731 | + * | |
| 732 | + * <spectrum type="NodeFunction"> | |
| 733 | + * <node> | |
| 734 | + * <parameter name="Energy" scale=".." value=".." min=".." max=".." free=".."/> | |
| 735 | + * <parameter name="Intensity" scale=".." value=".." min=".." max=".." free=".."/> | |
| 736 | + * </node> | |
| 737 | + * ... | |
| 738 | + * <node> | |
| 739 | + * <parameter name="Energy" scale=".." value=".." min=".." max=".." free=".."/> | |
| 740 | + * <parameter name="Intensity" scale=".." value=".." min=".." max=".." free=".."/> | |
| 741 | + * </node> | |
| 742 | + * </spectrum> | |
| 719 | 743 | ***************************************************************************/ |
| 720 | 744 | void GModelSpectralNodes::write(GXmlElement& xml) const |
| 721 | 745 | { |
| ... | ... | @@ -801,7 +825,320 @@ void GModelSpectralNodes::write(GXmlElement& xml) const |
| 801 | 825 | |
| 802 | 826 | |
| 803 | 827 | /***********************************************************************//** |
| 804 | - * @brief Print powerlaw information | |
| 828 | + * @brief Append node | |
| 829 | + * | |
| 830 | + * @param[in] energy Node energy. | |
| 831 | + * @param[in] intensity Node intensity. | |
| 832 | + * | |
| 833 | + * Appends one node to the node function. | |
| 834 | + ***************************************************************************/ | |
| 835 | +void GModelSpectralNodes::append(const GEnergy& energy, | |
| 836 | + const double& intensity) | |
| 837 | +{ | |
| 838 | + // Allocate node parameters | |
| 839 | + GModelPar e_par; | |
| 840 | + GModelPar i_par; | |
| 841 | + | |
| 842 | + // Set energy attributes | |
| 843 | + e_par.name("Energy"); | |
| 844 | + e_par.value(energy.MeV()); | |
| 845 | + e_par.unit("MeV"); | |
| 846 | + e_par.hasgrad(false); | |
| 847 | + | |
| 848 | + // Set intensity attributes | |
| 849 | + i_par.name("Intensity"); | |
| 850 | + i_par.value(intensity); | |
| 851 | + i_par.unit("ph/cm2/s/MeV"); | |
| 852 | + i_par.hasgrad(true); | |
| 853 | + | |
| 854 | + // Append to nodes | |
| 855 | + m_energies.push_back(e_par); | |
| 856 | + m_values.push_back(i_par); | |
| 857 | + | |
| 858 | + // Update parameter mapping | |
| 859 | + update_pars(); | |
| 860 | + | |
| 861 | + // Set pre-computation cache | |
| 862 | + set_cache(); | |
| 863 | + | |
| 864 | + // Return | |
| 865 | + return; | |
| 866 | +} | |
| 867 | + | |
| 868 | + | |
| 869 | +/***********************************************************************//** | |
| 870 | + * @brief Insert node | |
| 871 | + * | |
| 872 | + * @param[in] index Node index [0,...,nodes()-1]. | |
| 873 | + * @param[in] energy Node energy. | |
| 874 | + * @param[in] intensity Node intensity. | |
| 875 | + * | |
| 876 | + * @exception GException::out_of_range | |
| 877 | + * Node index is out of range. | |
| 878 | + * | |
| 879 | + * Inserts a node into the node function before the node with the specified | |
| 880 | + * @p index. | |
| 881 | + ***************************************************************************/ | |
| 882 | +void GModelSpectralNodes::insert(const int& index, | |
| 883 | + const GEnergy& energy, | |
| 884 | + const double& intensity) | |
| 885 | +{ | |
| 886 | + // Raise exception if index is outside boundary | |
| 887 | + #if defined(G_RANGE_CHECK) | |
| 888 | + if (m_energies.empty()) { | |
| 889 | + if (index > 0) { | |
| 890 | + throw GException::out_of_range(G_INSERT, index, 0, nodes()-1); | |
| 891 | + } | |
| 892 | + } | |
| 893 | + else { | |
| 894 | + if (index < 0 || index >= nodes()) { | |
| 895 | + throw GException::out_of_range(G_INSERT, index, 0, nodes()-1); | |
| 896 | + } | |
| 897 | + } | |
| 898 | + #endif | |
| 899 | + | |
| 900 | + // Allocate node parameters | |
| 901 | + GModelPar e_par; | |
| 902 | + GModelPar i_par; | |
| 903 | + | |
| 904 | + // Set energy attributes | |
| 905 | + e_par.name("Energy"); | |
| 906 | + e_par.value(energy.MeV()); | |
| 907 | + e_par.unit("MeV"); | |
| 908 | + e_par.hasgrad(false); | |
| 909 | + | |
| 910 | + // Set intensity attributes | |
| 911 | + i_par.name("Intensity"); | |
| 912 | + i_par.value(intensity); | |
| 913 | + i_par.unit("ph/cm2/s/MeV"); | |
| 914 | + i_par.hasgrad(true); | |
| 915 | + | |
| 916 | + // Insert node | |
| 917 | + m_energies.insert(m_energies.begin()+index, e_par); | |
| 918 | + m_values.insert(m_values.begin()+index, i_par); | |
| 919 | + | |
| 920 | + // Update parameter mapping | |
| 921 | + update_pars(); | |
| 922 | + | |
| 923 | + // Set pre-computation cache | |
| 924 | + set_cache(); | |
| 925 | + | |
| 926 | + // Return | |
| 927 | + return; | |
| 928 | +} | |
| 929 | + | |
| 930 | + | |
| 931 | +/***********************************************************************//** | |
| 932 | + * @brief Remove node | |
| 933 | + * | |
| 934 | + * @param[in] index Node index [0,...,nodes()-1]. | |
| 935 | + * | |
| 936 | + * @exception GException::out_of_range | |
| 937 | + * Node index is out of range. | |
| 938 | + * | |
| 939 | + * Removes node of specified @p index from the node function. | |
| 940 | + ***************************************************************************/ | |
| 941 | +void GModelSpectralNodes::remove(const int& index) | |
| 942 | +{ | |
| 943 | + // Raise exception if index is outside boundary | |
| 944 | + #if defined(G_RANGE_CHECK) | |
| 945 | + if (index < 0 || index >= nodes()) { | |
| 946 | + throw GException::out_of_range(G_REMOVE, index, 0, nodes()-1); | |
| 947 | + } | |
| 948 | + #endif | |
| 949 | + | |
| 950 | + // Erase energy and intensity | |
| 951 | + m_energies.erase(m_energies.begin() + index); | |
| 952 | + m_values.erase(m_values.begin() + index); | |
| 953 | + | |
| 954 | + // Update parameter mapping | |
| 955 | + update_pars(); | |
| 956 | + | |
| 957 | + // Set pre-computation cache | |
| 958 | + set_cache(); | |
| 959 | + | |
| 960 | + // Return | |
| 961 | + return; | |
| 962 | +} | |
| 963 | + | |
| 964 | + | |
| 965 | +/***********************************************************************//** | |
| 966 | + * @brief Reserve space for nodes | |
| 967 | + * | |
| 968 | + * @param[in] num Number of reseved nodes. | |
| 969 | + * | |
| 970 | + * Reserves space for @p num nodes. | |
| 971 | + ***************************************************************************/ | |
| 972 | +void GModelSpectralNodes::reserve(const int& num) | |
| 973 | +{ | |
| 974 | + // Reserve space | |
| 975 | + m_energies.reserve(num); | |
| 976 | + m_values.reserve(num); | |
| 977 | + | |
| 978 | + // Return | |
| 979 | + return; | |
| 980 | +} | |
| 981 | + | |
| 982 | + | |
| 983 | +/***********************************************************************//** | |
| 984 | + * @brief Append nodes from node function | |
| 985 | + * | |
| 986 | + * @param[in] nodes Node function. | |
| 987 | + * | |
| 988 | + * Appends all nodes from a node function to current object. | |
| 989 | + ***************************************************************************/ | |
| 990 | +void GModelSpectralNodes::extend(const GModelSpectralNodes& nodes) | |
| 991 | +{ | |
| 992 | + // Get number of nodes in node function. Note that we extract the size | |
| 993 | + // first to avoid an endless loop that arises when a container is | |
| 994 | + // appended to itself. | |
| 995 | + int num = nodes.nodes(); | |
| 996 | + | |
| 997 | + // Continue only if node function is not empty | |
| 998 | + if (num > 0) { | |
| 999 | + | |
| 1000 | + // Reserve enough space | |
| 1001 | + reserve(this->nodes() + num); | |
| 1002 | + | |
| 1003 | + // Loop over all nodes and append them to the node function | |
| 1004 | + for (int i = 0; i < num; ++i) { | |
| 1005 | + m_energies.push_back(nodes[2*i]); | |
| 1006 | + m_values.push_back(nodes[2*i+1]); | |
| 1007 | + } | |
| 1008 | + | |
| 1009 | + // Update parameter mapping | |
| 1010 | + update_pars(); | |
| 1011 | + | |
| 1012 | + // Set pre-computation cache | |
| 1013 | + set_cache(); | |
| 1014 | + | |
| 1015 | + } // endif: node function was not empty | |
| 1016 | + | |
| 1017 | + // Return | |
| 1018 | + return; | |
| 1019 | +} | |
| 1020 | + | |
| 1021 | + | |
| 1022 | +/***********************************************************************//** | |
| 1023 | + * @brief Return node energy | |
| 1024 | + * | |
| 1025 | + * @param[in] index Node index [0,...,nodes()-1]. | |
| 1026 | + * @return Energy of node @p index. | |
| 1027 | + * | |
| 1028 | + * @exception GException::out_of_range | |
| 1029 | + * Index is out of range. | |
| 1030 | + * | |
| 1031 | + * Returns the energy of node @p index. | |
| 1032 | + ***************************************************************************/ | |
| 1033 | +GEnergy GModelSpectralNodes::energy(const int& index) const | |
| 1034 | +{ | |
| 1035 | + // Raise an exception if index is out of range | |
| 1036 | + #if defined(G_RANGE_CHECK) | |
| 1037 | + if (index < 0 || index >= nodes()) { | |
| 1038 | + throw GException::out_of_range(G_ENERGY_GET, index, nodes()-1); | |
| 1039 | + } | |
| 1040 | + #endif | |
| 1041 | + | |
| 1042 | + // Retrieve energy | |
| 1043 | + GEnergy energy; | |
| 1044 | + energy.MeV(m_energies[index].value()); | |
| 1045 | + | |
| 1046 | + // Return energy | |
| 1047 | + return energy; | |
| 1048 | +} | |
| 1049 | + | |
| 1050 | + | |
| 1051 | +/***********************************************************************//** | |
| 1052 | + * @brief Set node energy | |
| 1053 | + * | |
| 1054 | + * @param[in] index Node index [0,...,nodes()-1]. | |
| 1055 | + * @param[in] energy Node energy. | |
| 1056 | + * | |
| 1057 | + * @exception GException::out_of_range | |
| 1058 | + * Index is out of range. | |
| 1059 | + * | |
| 1060 | + * Returns the energy of node @p index. | |
| 1061 | + ***************************************************************************/ | |
| 1062 | +void GModelSpectralNodes::energy(const int& index, const GEnergy& energy) | |
| 1063 | +{ | |
| 1064 | + // Raise an exception if index is out of range | |
| 1065 | + #if defined(G_RANGE_CHECK) | |
| 1066 | + if (index < 0 || index >= nodes()) { | |
| 1067 | + throw GException::out_of_range(G_ENERGY_SET, index, nodes()-1); | |
| 1068 | + } | |
| 1069 | + #endif | |
| 1070 | + | |
| 1071 | + // Set energy | |
| 1072 | + m_energies[index].value(energy.MeV()); | |
| 1073 | + | |
| 1074 | + // Set pre-computation cache | |
| 1075 | + set_cache(); | |
| 1076 | + | |
| 1077 | + // Return | |
| 1078 | + return; | |
| 1079 | +} | |
| 1080 | + | |
| 1081 | + | |
| 1082 | +/***********************************************************************//** | |
| 1083 | + * @brief Return node intensity | |
| 1084 | + * | |
| 1085 | + * @param[in] index Node index [0,...,nodes()-1]. | |
| 1086 | + * @return Energy of node @p index. | |
| 1087 | + * | |
| 1088 | + * @exception GException::out_of_range | |
| 1089 | + * Index is out of range. | |
| 1090 | + * | |
| 1091 | + * Returns the energy of node @p index. | |
| 1092 | + ***************************************************************************/ | |
| 1093 | +double GModelSpectralNodes::intensity(const int& index) const | |
| 1094 | +{ | |
| 1095 | + // Raise an exception if index is out of range | |
| 1096 | + #if defined(G_RANGE_CHECK) | |
| 1097 | + if (index < 0 || index >= nodes()) { | |
| 1098 | + throw GException::out_of_range(G_INTENSITY_GET, index, nodes()-1); | |
| 1099 | + } | |
| 1100 | + #endif | |
| 1101 | + | |
| 1102 | + // Return intensity | |
| 1103 | + return (m_values[index].value()); | |
| 1104 | +} | |
| 1105 | + | |
| 1106 | + | |
| 1107 | +/***********************************************************************//** | |
| 1108 | + * @brief Set node intensity | |
| 1109 | + * | |
| 1110 | + * @param[in] index Node index [0,...,nodes()-1]. | |
| 1111 | + * @param[in] energy Node energy. | |
| 1112 | + * | |
| 1113 | + * @exception GException::out_of_range | |
| 1114 | + * Index is out of range. | |
| 1115 | + * | |
| 1116 | + * Returns the energy of node @p index. | |
| 1117 | + ***************************************************************************/ | |
| 1118 | +void GModelSpectralNodes::intensity(const int& index, const double& intensity) | |
| 1119 | +{ | |
| 1120 | + // Raise an exception if index is out of range | |
| 1121 | + #if defined(G_RANGE_CHECK) | |
| 1122 | + if (index < 0 || index >= nodes()) { | |
| 1123 | + throw GException::out_of_range(G_INTENSITY_SET, index, nodes()-1); | |
| 1124 | + } | |
| 1125 | + #endif | |
| 1126 | + | |
| 1127 | + // Set intensity | |
| 1128 | + m_values[index].value(intensity); | |
| 1129 | + | |
| 1130 | + // Set pre-computation cache | |
| 1131 | + set_cache(); | |
| 1132 | + | |
| 1133 | + // Return | |
| 1134 | + return; | |
| 1135 | +} | |
| 1136 | + | |
| 1137 | + | |
| 1138 | +/***********************************************************************//** | |
| 1139 | + * @brief Print node function information | |
| 1140 | + * | |
| 1141 | + * @return String containing node function information. | |
| 805 | 1142 | ***************************************************************************/ |
| 806 | 1143 | std::string GModelSpectralNodes::print(void) const |
| 807 | 1144 | { |
| ... | ... | @@ -810,6 +1147,8 @@ std::string GModelSpectralNodes::print(void) const |
| 810 | 1147 | |
| 811 | 1148 | // Append header |
| 812 | 1149 | result.append("=== GModelSpectralNodes ==="); |
| 1150 | + | |
| 1151 | + // Append information | |
| 813 | 1152 | result.append("\n"+parformat("Number of nodes")+str(m_energies.size())); |
| 814 | 1153 | result.append("\n"+parformat("Number of parameters")+str(size())); |
| 815 | 1154 | for (int i = 0; i < size(); ++i) { |
| ... | ... | @@ -1310,10 +1649,3 @@ void GModelSpectralNodes::mc_update(const GEnergy& emin, const GEnergy& emax) co |
| 1310 | 1649 | // Return |
| 1311 | 1650 | return; |
| 1312 | 1651 | } |
| 1313 | - | |
| 1314 | - | |
| 1315 | -/*========================================================================== | |
| 1316 | - = = | |
| 1317 | - = Friends = | |
| 1318 | - = = | |
| 1319 | - ==========================================================================*/ | ... | ... |