GammaLib  2.1.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GModelSpectralExpPlaw.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GModelSpectralExpPlaw.cpp - Exponential cut off power law model *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2010-2021 by Juergen Knoedlseder *
5  * ----------------------------------------------------------------------- *
6  * *
7  * This program is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19  * *
20  ***************************************************************************/
21 /**
22  * @file GModelSpectralExpPlaw.cpp
23  * @brief Exponential cut off power law spectral class implementation
24  * @author Juergen Knoedlseder
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include <cmath>
32 #include "GException.hpp"
33 #include "GTools.hpp"
34 #include "GRan.hpp"
35 #include "GIntegral.hpp"
38 
39 /* __ Constants __________________________________________________________ */
40 
41 /* __ Globals ____________________________________________________________ */
42 const GModelSpectralExpPlaw g_spectral_eplaw_seed1("ExponentialCutoffPowerLaw",
43  "Prefactor",
44  "Index",
45  "PivotEnergy",
46  "CutoffEnergy");
47 const GModelSpectralRegistry g_spectral_eplaw_registry1(&g_spectral_eplaw_seed1);
48 #if defined(G_LEGACY_XML_FORMAT)
49 const GModelSpectralExpPlaw g_spectral_eplaw_seed2("ExpCutoff",
50  "Prefactor",
51  "Index",
52  "Scale",
53  "Cutoff");
54 const GModelSpectralRegistry g_spectral_eplaw_registry2(&g_spectral_eplaw_seed2);
55 #endif
56 
57 /* __ Method name definitions ____________________________________________ */
58 #define G_MC "GModelSpectralExpPlaw::mc(GEnergy&, GEnergy&, GTime&, GRan&)"
59 #define G_READ "GModelSpectralExpPlaw::read(GXmlElement&)"
60 #define G_WRITE "GModelSpectralExpPlaw::write(GXmlElement&)"
61 
62 /* __ Macros _____________________________________________________________ */
63 
64 /* __ Coding definitions _________________________________________________ */
65 
66 /* __ Debug definitions __________________________________________________ */
67 //#define G_DEBUG_MC //!< Debug Monte-Carlo sampling
68 
69 
70 /*==========================================================================
71  = =
72  = Constructors/destructors =
73  = =
74  ==========================================================================*/
75 
76 /***********************************************************************//**
77  * @brief Void constructor
78  ***************************************************************************/
80 {
81  // Initialise members
82  init_members();
83 
84  // Return
85  return;
86 }
87 
88 
89 /***********************************************************************//**
90  * @brief Model type and parameter name constructor
91  *
92  * @param[in] type Model type.
93  * @param[in] prefactor Name of prefactor parameter.
94  * @param[in] index Name of index parameter.
95  * @param[in] pivot Name of pivot parameter.
96  * @param[in] cutoff Name of cutoff parameter.
97  ***************************************************************************/
99  const std::string& prefactor,
100  const std::string& index,
101  const std::string& pivot,
102  const std::string& cutoff) :
104 {
105  // Initialise members
106  init_members();
107 
108  // Set model type
109  m_type = type;
110 
111  // Set parameter names
112  m_norm.name(prefactor);
113  m_index.name(index);
114  m_pivot.name(pivot);
115  m_ecut.name(cutoff);
116 
117  // Return
118  return;
119 }
120 
121 
122 /***********************************************************************//**
123  * @brief Constructor
124  *
125  * @param[in] prefactor Pre factor normalization (ph/cm2/s/MeV).
126  * @param[in] index Power law index.
127  * @param[in] pivot Pivot energy.
128  * @param[in] cutoff Cut off energy.
129  *
130  * Construct an exponentially cut off power law from
131  * - a prefactor value (in units of ph/cm2/s/MeV)
132  * - a spectral index,
133  * - a pivot energy, and
134  * - a cut off energy.
135  ***************************************************************************/
137  const double& index,
138  const GEnergy& pivot,
139  const GEnergy& cutoff) :
141 {
142  // Initialise members
143  init_members();
144 
145  // Set parameters
146  m_norm.value(prefactor);
147  m_index.value(index);
148  m_pivot.value(pivot.MeV()); // Internally stored in MeV
149  m_ecut.value(cutoff.MeV()); // Internally stored in MeV
150 
151  // Autoscale parameters
152  autoscale();
153 
154  // Return
155  return;
156 }
157 
158 
159 /***********************************************************************//**
160  * @brief XML constructor
161  *
162  * @param[in] xml XML element.
163  *
164  * Constructs an exponentially cut off power law spectral model by extracting
165  * information from an XML element. See the read() method for more
166  * information about the expected structure of the XML element.
167  ***************************************************************************/
170 {
171  // Initialise members
172  init_members();
173 
174  // Read information from XML element
175  read(xml);
176 
177  // Return
178  return;
179 }
180 
181 
182 /***********************************************************************//**
183  * @brief Copy constructor
184  *
185  * @param[in] model Exponentially cut off power law model.
186  ***************************************************************************/
188  GModelSpectral(model)
189 {
190  // Initialise members
191  init_members();
192 
193  // Copy members
194  copy_members(model);
195 
196  // Return
197  return;
198 }
199 
200 
201 /***********************************************************************//**
202  * @brief Destructor
203  ***************************************************************************/
205 {
206  // Free members
207  free_members();
208 
209  // Return
210  return;
211 }
212 
213 
214 /*==========================================================================
215  = =
216  = Operators =
217  = =
218  ==========================================================================*/
219 
220 /***********************************************************************//**
221  * @brief Assignment operator
222  *
223  * @param[in] model Exponentially cut off power law model.
224  * @return Exponentially cut off power law model.
225  ***************************************************************************/
227 {
228  // Execute only if object is not identical
229  if (this != &model) {
230 
231  // Copy base class members
232  this->GModelSpectral::operator=(model);
233 
234  // Free members
235  free_members();
236 
237  // Initialise members
238  init_members();
239 
240  // Copy members
241  copy_members(model);
242 
243  } // endif: object was not identical
244 
245  // Return
246  return *this;
247 }
248 
249 
250 /*==========================================================================
251  = =
252  = Public methods =
253  = =
254  ==========================================================================*/
255 
256 /***********************************************************************//**
257  * @brief Clear exponentially cut off power law model
258  ***************************************************************************/
260 {
261  // Free class members (base and derived classes, derived class first)
262  free_members();
264 
265  // Initialise members
267  init_members();
268 
269  // Return
270  return;
271 }
272 
273 
274 /***********************************************************************//**
275  * @brief Clone exponentially cut off power law model
276  *
277  * @return Pointer to deep copy of exponentially cut off power law model.
278  ***************************************************************************/
280 {
281  // Clone exponentially cut off power law model
282  return new GModelSpectralExpPlaw(*this);
283 }
284 
285 
286 /***********************************************************************//**
287  * @brief Evaluate function
288  *
289  * @param[in] srcEng True photon energy.
290  * @param[in] srcTime True photon arrival time.
291  * @param[in] gradients Compute gradients?
292  * @return Model value (ph/cm2/s/MeV).
293  *
294  * Evaluates
295  *
296  * \f[
297  * S_{\rm E}(E | t) = {\tt m\_norm}
298  * \left( \frac{E}{\tt m\_pivot} \right)^{\tt m\_index}
299  * \exp \left( \frac{-E}{\tt m\_ecut} \right)
300  * \f]
301  *
302  * where
303  * - \f${\tt m\_norm}\f$ is the normalization or prefactor,
304  * - \f${\tt m\_pivot}\f$ is the pivot energy,
305  * - \f${\tt m\_index}\f$ is the spectral index, and
306  * - \f${\tt m\_ecut}\f$ is the cut off energy.
307  *
308  * If the @p gradients flag is true the method will also compute the
309  * partial derivatives of the model with respect to the parameters using
310  *
311  * \f[
312  * \frac{\delta S_{\rm E}(E | t)}{\delta {\tt m\_norm}} =
313  * \frac{S_{\rm E}(E | t)}{{\tt m\_norm}}
314  * \f]
315  *
316  * \f[
317  * \frac{\delta S_{\rm E}(E | t)}{\delta {\tt m\_index}} =
318  * S_{\rm E}(E | t) \, \ln(E/{\tt m_pivot})
319  * \f]
320  *
321  * \f[
322  * \frac{\delta S_{\rm E}(E | t)}{\delta {\tt m\_ecut}} =
323  * S_{\rm E}(E | t) \, \left( \frac{E}{{\tt m\_ecut}^2} \right)
324  * \f]
325  *
326  * \f[
327  * \frac{\delta S_{\rm E}(E | t)}{\delta {\tt m\_pivot}} =
328  * -S_{\rm E}(E | t) \,
329  * \left( \frac{{\tt m\_index}}{{\tt m\_pivot}} \right)
330  * \f]
331  *
332  * @todo The method expects that pivot!=0 and ecut!=0. Otherwise Inf or NaN
333  * may result. We should add a test that prevents using invalid
334  * values.
335  ***************************************************************************/
337  const GTime& srcTime,
338  const bool& gradients) const
339 {
340  // Update the evaluation cache
341  update_eval_cache(srcEng);
342 
343  // Compute function value
344  double value = m_norm.value() * m_last_power;
345 
346  // Optionally compute gradients
347  if (gradients) {
348 
349  // Compute partial derivatives with respect to the parameter factor
350  // values. The partial derivatives with respect to the parameter
351  // values are obtained by division by the scale factor.
352  double g_norm = (m_norm.is_free())
354  : 0.0;
355  double g_index = (m_index.is_free())
356  ? value * m_index.scale() * std::log(m_last_e_norm)
357  : 0.0;
358  double g_ecut = (m_ecut.is_free() && m_ecut.factor_value() != 0.0)
359  ? value * m_last_e_cut / m_ecut.factor_value()
360  : 0.0;
361  double g_pivot = (m_pivot.is_free() && m_pivot.factor_value() != 0.0)
362  ? -value * m_last_index / m_pivot.factor_value()
363  : 0.0;
364 
365  // Set gradients
366  m_norm.factor_gradient(g_norm);
367  m_index.factor_gradient(g_index);
368  m_ecut.factor_gradient(g_ecut);
369  m_pivot.factor_gradient(g_pivot);
370 
371  } // endif: gradient computation was requested
372 
373  // Compile option: Check for NaN/Inf
374  #if defined(G_NAN_CHECK)
375  if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) {
376  std::cout << "*** ERROR: GModelSpectralExpPlaw::eval";
377  std::cout << "(srcEng=" << srcEng;
378  std::cout << ", srcTime=" << srcTime << "):";
379  std::cout << " NaN/Inf encountered";
380  std::cout << " (value=" << value;
381  std::cout << ", power=" << m_last_power;
382  std::cout << ")" << std::endl;
383  }
384  #endif
385 
386  // Return
387  return value;
388 }
389 
390 
391 /***********************************************************************//**
392  * @brief Returns model photon flux between [emin, emax] (units: ph/cm2/s)
393  *
394  * @param[in] emin Minimum photon energy.
395  * @param[in] emax Maximum photon energy.
396  * @return Photon flux (ph/cm2/s).
397  *
398  * Computes
399  *
400  * \f[
401  * \int_{\tt emin}^{\tt emax} S_{\rm E}(E | t) dE
402  * \f]
403  *
404  * where
405  * - [@p emin, @p emax] is an energy interval, and
406  * - \f$S_{\rm E}(E | t)\f$ is the spectral model (ph/cm2/s/MeV).
407  * The integration is done numerically.
408  ***************************************************************************/
410  const GEnergy& emax) const
411 {
412  // Initialise flux
413  double flux = 0.0;
414 
415  // Compute only if integration range is valid
416  if (emin < emax) {
417 
418  // Setup integration kernel
419  flux_kernel integrand(m_norm.value(), m_index.value(),
420  m_pivot.value(), m_ecut.value());
421  GIntegral integral(&integrand);
422 
423  // Get integration boundaries in MeV
424  double e_min = emin.MeV();
425  double e_max = emax.MeV();
426 
427  // Perform integration
428  flux = integral.romberg(e_min, e_max);
429 
430  } // endif: integration range was valid
431 
432  // Return
433  return flux;
434 }
435 
436 
437 /***********************************************************************//**
438  * @brief Returns model energy flux between [emin, emax] (units: erg/cm2/s)
439  *
440  * @param[in] emin Minimum photon energy.
441  * @param[in] emax Maximum photon energy.
442  * @return Energy flux (erg/cm2/s).
443  *
444  * Computes
445  *
446  * \f[
447  * \int_{\tt emin}^{\tt emax} S_{\rm E}(E | t) E \, dE
448  * \f]
449  *
450  * where
451  * - [@p emin, @p emax] is an energy interval, and
452  * - \f$S_{\rm E}(E | t)\f$ is the spectral model (ph/cm2/s/MeV).
453  * The integration is done numerically.
454  ***************************************************************************/
456  const GEnergy& emax) const
457 {
458  // Initialise flux
459  double eflux = 0.0;
460 
461  // Compute only if integration range is valid
462  if (emin < emax) {
463 
464  // Setup integration kernel
465  eflux_kernel integrand(m_norm.value(), m_index.value(),
466  m_pivot.value(), m_ecut.value());
467  GIntegral integral(&integrand);
468 
469  // Get integration boundaries in MeV
470  double e_min = emin.MeV();
471  double e_max = emax.MeV();
472 
473  // Perform integration
474  eflux = integral.romberg(e_min, e_max);
475 
476  // Convert from MeV/cm2/s to erg/cm2/s
477  eflux *= gammalib::MeV2erg;
478 
479  } // endif: integration range was valid
480 
481  // Return
482  return eflux;
483 }
484 
485 
486 /***********************************************************************//**
487  * @brief Returns MC energy between [emin, emax]
488  *
489  * @param[in] emin Minimum photon energy.
490  * @param[in] emax Maximum photon energy.
491  * @param[in] time True photon arrival time.
492  * @param[in,out] ran Random number generator.
493  * @return Energy.
494  *
495  * Simulates a random energy in the interval [emin, emax] for an
496  * exponentially cut off power law. The simulation is done using a rejection
497  * method. First, a random energy within [emin, emax] is drawn from an
498  * power law distribution. Then the energy is accepted or rejected based
499  * on an acceptance fraction that is computed from the exponential cut off.
500  ***************************************************************************/
502  const GEnergy& emax,
503  const GTime& time,
504  GRan& ran) const
505 {
506  // Check energy interval
508 
509  // Allocate energy
510  GEnergy energy;
511 
512  // Update cache
513  update_mc_cache(emin, emax);
514 
515  // Initialise energy
516  double eng;
517 
518  // Initialise acceptance fraction
519  double acceptance_fraction;
520  double inv_ecut = 1.0 / m_ecut.value();
521 
522  // Compute random number generator normalisation for speed-up of the
523  // computations. Normally it should be sufficient to always use the
524  // minimum energy for the normalisation, yet for the case that the model
525  // grows with energy we better also test the maximum energy, and we
526  // just use the larger of both normalisations
527  double norm_emin = std::exp(-emin.MeV() * inv_ecut);
528  double norm_emax = std::exp(-emax.MeV() * inv_ecut);
529  double norm = (norm_emin > norm_emax) ? norm_emin : norm_emax;
530 
531  // Debug option: initialise number of samples
532  #if defined(G_DEBUG_MC)
533  int samples = 0;
534  #endif
535 
536  // Use rejection method to draw a random energy. We first draw
537  // analytically from a power law, and then compare the power law
538  // at the drawn energy to the exponentially cut off function. This
539  // gives an acceptance fraction, and we accept the energy only if
540  // a uniform random number is <= the acceptance fraction.
541  do {
542 
543  // Debug option: increment number of samples
544  #if defined(G_DEBUG_MC)
545  samples++;
546  #endif
547 
548  // Get uniform random number
549  double u = ran.uniform();
550 
551  // Case A: Index is not -1
552  if (index() != -1.0) {
553  if (u > 0.0) {
555  m_mc_exponent);
556  }
557  else {
558  eng = 0.0;
559  }
560  }
561 
562  // Case B: Index is -1
563  else {
565  }
566 
567  // Compute acceptance fraction
568  acceptance_fraction = std::exp(-eng * inv_ecut);
569 
570  } while (ran.uniform() * norm > acceptance_fraction);
571 
572  // Set energy
573  energy.MeV(eng);
574 
575  // Debug option: write result
576  #if defined(G_DEBUG_MC)
577  std::cout << "GModelSpectralExpPlaw::mc(";
578  std::cout << emin.print() << "," << emax.print() << "," << time.print() << "):";
579  std::cout << " energy=" << energy.print();
580  std::cout << " samples=" << samples << std::endl;
581  #endif
582 
583  // Return energy
584  return energy;
585 }
586 
587 
588 /***********************************************************************//**
589  * @brief Read model from XML element
590  *
591  * @param[in] xml XML element.
592  *
593  * Reads the spectral information from an XML element.
594  ***************************************************************************/
596 {
597  // Verify number of model parameters
599 
600  // Get parameter pointers
603  const GXmlElement* ecut = gammalib::xml_get_par(G_READ, xml, m_ecut.name());
605 
606  // Read parameters
607  m_norm.read(*norm);
608  m_index.read(*index);
609  m_ecut.read(*ecut);
610  m_pivot.read(*pivot);
611 
612  // Return
613  return;
614 }
615 
616 
617 /***********************************************************************//**
618  * @brief Write model into XML element
619  *
620  * @param[in] xml XML element.
621  *
622  * Writes the spectral information into an XML element.
623  ***************************************************************************/
625 {
626  // Verify model type
628 
629  // Get XML parameters
634 
635  // Write parameters
636  m_norm.write(*norm);
637  m_index.write(*index);
638  m_ecut.write(*ecut);
639  m_pivot.write(*pivot);
640 
641  // Return
642  return;
643 }
644 
645 
646 /***********************************************************************//**
647  * @brief Print model information
648  *
649  * @param[in] chatter Chattiness.
650  * @return String containing model information.
651  ***************************************************************************/
652 std::string GModelSpectralExpPlaw::print(const GChatter& chatter) const
653 {
654  // Initialise result string
655  std::string result;
656 
657  // Continue only if chatter is not silent
658  if (chatter != SILENT) {
659 
660  // Append header
661  result.append("=== GModelSpectralExpPlaw ===");
662 
663  // Append information
664  result.append("\n"+gammalib::parformat("Number of parameters"));
665  result.append(gammalib::str(size()));
666  for (int i = 0; i < size(); ++i) {
667  result.append("\n"+m_pars[i]->print(chatter));
668  }
669 
670  } // endif: chatter was not silent
671 
672  // Return result
673  return result;
674 }
675 
676 
677 /*==========================================================================
678  = =
679  = Private methods =
680  = =
681  ==========================================================================*/
682 
683 /***********************************************************************//**
684  * @brief Initialise class members
685  ***************************************************************************/
687 {
688  // Initialise model type
689  m_type = "ExponentialCutoffPowerLaw";
690 
691  // Initialise powerlaw normalisation
692  m_norm.clear();
693  m_norm.name("Prefactor");
694  m_norm.unit("ph/cm2/s/MeV");
695  m_norm.scale(1.0);
696  m_norm.value(1.0); // default: 1.0
697  m_norm.min(0.0); // min: 0.0
698  m_norm.free();
699  m_norm.gradient(0.0);
700  m_norm.has_grad(true);
701 
702  // Initialise powerlaw index
703  m_index.clear();
704  m_index.name("Index");
705  m_index.scale(1.0);
706  m_index.value(-2.0); // default: -2.0
707  m_index.range(-10.0,+10.0); // range: [-10,+10]
708  m_index.free();
709  m_index.gradient(0.0);
710  m_index.has_grad(true);
711 
712  // Initialise cut off energy
713  m_ecut.clear();
714  m_ecut.name("CutoffEnergy");
715  m_ecut.unit("MeV");
716  m_ecut.scale(1.0);
717  m_ecut.value(1000.0); // default: 1000.0
718  m_ecut.min(0.1); // min: 0.1
719  m_ecut.free();
720  m_ecut.gradient(0.0);
721  m_ecut.has_grad(true);
722 
723  // Initialise pivot energy
724  m_pivot.clear();
725  m_pivot.name("PivotEnergy");
726  m_pivot.unit("MeV");
727  m_pivot.scale(1.0);
728  m_pivot.value(100.0);
729  m_pivot.fix();
730  m_pivot.gradient(0.0);
731  m_pivot.has_grad(true);
732 
733  // Set parameter pointer(s)
734  m_pars.clear();
735  m_pars.push_back(&m_norm);
736  m_pars.push_back(&m_index);
737  m_pars.push_back(&m_ecut);
738  m_pars.push_back(&m_pivot);
739 
740  // Initialise eval cache
742  m_last_index = 1.0e30;
743  m_last_ecut = 1.0e30;
744  m_last_pivot = 1.0e30;
745  m_last_e_norm = 0.0;
746  m_last_e_cut = 0.0;
747  m_last_power = 0.0;
748 
749  // Initialise MC cache
750  m_mc_emin = 0.0;
751  m_mc_emax = 0.0;
752  m_mc_exponent = 0.0;
753  m_mc_pow_emin = 0.0;
754  m_mc_pow_ewidth = 0.0;
755 
756  // Return
757  return;
758 }
759 
760 
761 /***********************************************************************//**
762  * @brief Copy class members
763  *
764  * @param[in] model Exponential cut off power law model.
765  ***************************************************************************/
767 {
768  // Copy members
769  m_type = model.m_type;
770  m_norm = model.m_norm;
771  m_index = model.m_index;
772  m_ecut = model.m_ecut;
773  m_pivot = model.m_pivot;
774 
775  // Set parameter pointer(s)
776  m_pars.clear();
777  m_pars.push_back(&m_norm);
778  m_pars.push_back(&m_index);
779  m_pars.push_back(&m_ecut);
780  m_pars.push_back(&m_pivot);
781 
782  // Copy eval cache
784  m_last_index = model.m_last_index;
785  m_last_ecut = model.m_last_ecut;
786  m_last_pivot = model.m_last_pivot;
788  m_last_e_cut = model.m_last_e_cut;
789  m_last_power = model.m_last_power;
790 
791  // Copy MC cache
792  m_mc_emin = model.m_mc_emin;
793  m_mc_emax = model.m_mc_emax;
797 
798  // Return
799  return;
800 }
801 
802 
803 /***********************************************************************//**
804  * @brief Delete class members
805  ***************************************************************************/
807 {
808  // Return
809  return;
810 }
811 
812 
813 /***********************************************************************//**
814  * @brief Update eval precomputation cache
815  *
816  * @param[in] energy Energy.
817  *
818  * Updates the precomputation cache for eval() method.
819  ***************************************************************************/
821 {
822  // Get parameter values (takes 3 multiplications which are difficult
823  // to avoid)
824  double index = m_index.value();
825  double ecut = m_ecut.value();
826  double pivot = m_pivot.value();
827 
828  // If the energy or one of the parameters index, cut-off or pivot
829  // energy has changed then recompute the cache
830  if ((m_last_energy != energy) ||
831  (m_last_index != index) ||
832  (m_last_ecut != ecut) ||
833  (m_last_pivot != pivot)) {
834 
835  // Store actual energy and parameter values
836  m_last_energy = energy;
838  m_last_ecut = ecut;
840 
841  // Compute and store value
842  double eng = energy.MeV();
843  m_last_e_norm = eng / m_last_pivot;
844  m_last_e_cut = eng / m_last_ecut;
847  } // endif: recomputation was required
848 
849  // Return
850  return;
851 }
852 
853 
854 /***********************************************************************//**
855  * @brief Update Monte Carlo pre computation cache
856  *
857  * @param[in] emin Minimum photon energy.
858  * @param[in] emax Maximum photon energy.
859  *
860  * Updates the precomputation cache for Monte Carlo simulations.
861  ***************************************************************************/
863  const GEnergy& emax) const
864 
865 {
866  // Case A: Index is not -1
867  if (index() != -1.0) {
868 
869  // Change in energy boundaries?
870  if (emin.MeV() != m_mc_emin || emax.MeV() != m_mc_emax) {
871  m_mc_emin = emin.MeV();
872  m_mc_emax = emax.MeV();
873  m_mc_exponent = index() + 1.0;
876  }
877 
878  }
879 
880  // Case B: Index is -1
881  else {
882 
883  // Change in energy boundaries?
884  if (emin.MeV() != m_mc_emin || emax.MeV() != m_mc_emax) {
885  m_mc_emin = emin.MeV();
886  m_mc_emax = emax.MeV();
887  m_mc_exponent = 0.0;
890  }
891 
892  }
893 
894  // Return
895  return;
896 }
897 
898 
899 /***********************************************************************//**
900  * @brief Kernel for photon flux integration
901  *
902  * @param[in] energy Energy (MeV).
903  ***************************************************************************/
904 double GModelSpectralExpPlaw::flux_kernel::eval(const double& energy)
905 {
906  // Evaluate function value
907  double e_norm = energy * m_inv_pivot;
908  double e_cut = energy * m_inv_ecut;
909  double power = std::pow(e_norm, m_index) * std::exp(-e_cut);
910  double value = m_norm * power;
911 
912  // Return value
913  return value;
914 }
915 
916 
917 /***********************************************************************//**
918  * @brief Kernel for energy flux integration
919  *
920  * @param[in] energy Energy (MeV).
921  ***************************************************************************/
922 double GModelSpectralExpPlaw::eflux_kernel::eval(const double& energy)
923 {
924  // Evaluate function value
925  double e_norm = energy * m_inv_pivot;
926  double e_cut = energy * m_inv_ecut;
927  double power = std::pow(e_norm, m_index) * std::exp(-e_cut);
928  double value = m_norm * power * energy;
929 
930  // Return value
931  return value;
932 }
const double & factor_gradient(void) const
Return parameter factor gradient.
double m_last_e_norm
Last E/Epivot value.
double norm(const GVector &vector)
Computes vector norm.
Definition: GVector.cpp:864
#define G_MC
double m_mc_emax
Maximum energy.
const std::string & name(void) const
Return parameter name.
Random number generator class definition.
Abstract spectral model base class.
double m_last_index
Last index parameter.
double gradient(void) const
Return parameter gradient.
int size(void) const
Return number of parameters.
virtual GModelSpectral & operator=(const GModelSpectral &model)
Assignment operator.
virtual std::string type(void) const
Return model type.
void write(GXmlElement &xml) const
Set or update parameter attributes in XML element.
Definition: GModelPar.cpp:351
virtual void write(GXmlElement &xml) const
Write model into XML element.
void copy_members(const GModelSpectralExpPlaw &model)
Copy class members.
std::vector< GModelPar * > m_pars
Parameter pointers.
double m_mc_exponent
Exponent (index+1)
GEnergy pivot(void) const
Return pivot energy.
XML element node class.
Definition: GXmlElement.hpp:48
Spectral model registry class definition.
double eval(const double &eng)
Kernel for photon flux integration.
Random number generator class.
Definition: GRan.hpp:44
double MeV(void) const
Return energy in MeV.
Definition: GEnergy.cpp:321
virtual double eflux(const GEnergy &emin, const GEnergy &emax) const
Returns model energy flux between emin, emax
Time class.
Definition: GTime.hpp:55
Gammalib tools definition.
GIntegral class interface definition.
Definition: GIntegral.hpp:46
void free_members(void)
Delete class members.
double min(void) const
Return parameter minimum boundary.
bool is_free(void) const
Signal if parameter is free.
GModelPar m_ecut
Exponential cut off energy.
bool is_notanumber(const double &x)
Signal if argument is not a number.
Definition: GTools.hpp:201
const GModelSpectralExpPlaw g_spectral_eplaw_seed1("ExponentialCutoffPowerLaw","Prefactor","Index","PivotEnergy","CutoffEnergy")
const double & scale(void) const
Return parameter scale.
bool is_infinite(const double &x)
Signal if argument is infinite.
Definition: GTools.hpp:184
bool has_grad(void) const
Signal if parameter gradient is computed analytically.
virtual ~GModelSpectralExpPlaw(void)
Destructor.
virtual double eval(const GEnergy &srcEng, const GTime &srcTime=GTime(), const bool &gradients=false) const
Evaluate function.
GModelPar m_norm
Normalization factor.
virtual void read(const GXmlElement &xml)
Read model from XML element.
virtual GEnergy mc(const GEnergy &emin, const GEnergy &emax, const GTime &time, GRan &ran) const
Returns MC energy between [emin, emax].
std::string print(const GChatter &chatter=NORMAL) const
Print energy.
Definition: GEnergy.cpp:748
virtual void clear(void)
Clear exponentially cut off power law model.
void free(void)
Free a parameter.
void fix(void)
Fix a parameter.
GXmlElement * xml_need_par(const std::string &origin, GXmlElement &xml, const std::string &name)
Return pointer to parameter with given name in XML element.
Definition: GTools.cpp:1637
GVector log(const GVector &vector)
Computes natural logarithm of vector elements.
Definition: GVector.cpp:1274
double m_last_ecut
Last energy cut-off parameter.
double uniform(void)
Returns random double precision floating value in range 0 to 1.
Definition: GRan.cpp:242
double m_mc_emin
Minimum energy.
void check_energy_interval(const std::string &origin, const GEnergy &emin, const GEnergy &emax)
Checks energy interval.
Definition: GException.cpp:364
void clear(void)
Clear parameter.
GModelSpectralExpPlaw(void)
Void constructor.
double index(void) const
Return power law index.
GChatter
Definition: GTypemaps.hpp:33
std::string print(const GChatter &chatter=NORMAL) const
Print time.
Definition: GTime.cpp:1188
GEnergy m_last_energy
Last energy value.
std::string m_type
Model type.
double m_last_pivot
Last pivot parameter.
void xml_check_parnum(const std::string &origin, const GXmlElement &xml, const int &number)
Checks number of parameters.
Definition: GTools.cpp:1777
Interface definition for the spectral model registry class.
void autoscale(void)
Autoscale parameters.
virtual std::string print(const GChatter &chatter=NORMAL) const
Print model information.
double m_last_power
Last power value.
void init_members(void)
Initialise class members.
double m_mc_pow_emin
Power of minimum energy.
const double MeV2erg
Definition: GTools.hpp:45
void update_mc_cache(const GEnergy &emin, const GEnergy &emax) const
Update Monte Carlo pre computation cache.
void range(const double &min, const double &max)
Set minimum and maximum parameter boundaries.
void read(const GXmlElement &xml)
Extract parameter attributes from XML element.
Definition: GModelPar.cpp:229
double value(void) const
Return parameter value.
void update_eval_cache(const GEnergy &energy) const
Update eval precomputation cache.
GVector pow(const GVector &vector, const double &power)
Computes tanh of vector elements.
Definition: GVector.cpp:1422
const std::string & unit(void) const
Return parameter unit.
Exception handler interface definition.
virtual double flux(const GEnergy &emin, const GEnergy &emax) const
Returns model photon flux between emin, emax
Exponential cut off power law spectral class.
#define G_READ
double eval(const double &eng)
Kernel for energy flux integration.
GVector exp(const GVector &vector)
Computes exponential of vector elements.
Definition: GVector.cpp:1232
GModelPar m_pivot
Pivot energy.
virtual GModelSpectralExpPlaw & operator=(const GModelSpectralExpPlaw &model)
Assignment operator.
void init_members(void)
Initialise class members.
Exponential cut off power law spectral class interface definition.
virtual GModelSpectralExpPlaw * clone(void) const
Clone exponentially cut off power law model.
#define G_WRITE
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1143
GModelPar m_index
Spectral index.
Integration class interface definition.
double m_last_e_cut
Last E/Ecut value.
const GXmlElement * xml_get_par(const std::string &origin, const GXmlElement &xml, const std::string &name)
Return pointer to parameter with given name in XML element.
Definition: GTools.cpp:1689
void free_members(void)
Delete class members.
void clear(void)
Clear instance.
Definition: GEnergy.cpp:261
const double & factor_value(void) const
Return parameter factor value.
Class that handles energies in a unit independent way.
Definition: GEnergy.hpp:48
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:489
double m_mc_pow_ewidth
Power of energy width.
void xml_check_type(const std::string &origin, GXmlElement &xml, const std::string &type)
Checks the model type.
Definition: GTools.cpp:1819