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