00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 #include <cmath>
00032 #include "GException.hpp"
00033 #include "GTools.hpp"
00034 #include "GMath.hpp"
00035 #include "GRan.hpp"
00036 #include "GModelSpectralPlaw2.hpp"
00037 #include "GModelSpectralRegistry.hpp"
00038
00039
00040
00041
00042 const GModelSpectralPlaw2 g_spectral_plaw2_seed1("PowerLaw",
00043 "PhotonFlux",
00044 "Index",
00045 "LowerLimit",
00046 "UpperLimit");
00047 const GModelSpectralRegistry g_spectral_plaw2_registry1(&g_spectral_plaw2_seed1);
00048 #if defined(G_LEGACY_XML_FORMAT)
00049 const GModelSpectralPlaw2 g_spectral_plaw2_seed2("PowerLaw2",
00050 "Integral",
00051 "Index",
00052 "LowerLimit",
00053 "UpperLimit");
00054 const GModelSpectralRegistry g_spectral_plaw2_registry2(&g_spectral_plaw2_seed2);
00055 #endif
00056
00057
00058 #define G_FLUX "GModelSpectralPlaw2::flux(GEnergy&, GEnergy&)"
00059 #define G_EFLUX "GModelSpectralPlaw2::eflux(GEnergy&, GEnergy&)"
00060 #define G_MC "GModelSpectralPlaw2::mc(GEnergy&, GEnergy&, GTime&, GRan&)"
00061 #define G_READ "GModelSpectralPlaw2::read(GXmlElement&)"
00062 #define G_WRITE "GModelSpectralPlaw2::write(GXmlElement&)"
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 GModelSpectralPlaw2::GModelSpectralPlaw2(void) : GModelSpectral()
00083 {
00084
00085 init_members();
00086
00087
00088 return;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 GModelSpectralPlaw2::GModelSpectralPlaw2(const std::string& type,
00102 const std::string& integral,
00103 const std::string& index,
00104 const std::string& emin,
00105 const std::string& emax) :
00106 GModelSpectral()
00107 {
00108
00109 init_members();
00110
00111
00112 m_type = type;
00113
00114
00115 m_integral.name(integral);
00116 m_index.name(index);
00117 m_emin.name(emin);
00118 m_emax.name(emax);
00119
00120
00121 return;
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 GModelSpectralPlaw2::GModelSpectralPlaw2(const double& integral,
00140 const double& index,
00141 const GEnergy& emin,
00142 const GEnergy& emax) :
00143 GModelSpectral()
00144 {
00145
00146 init_members();
00147
00148
00149 m_integral.value(integral);
00150 m_index.value(index);
00151 m_emin.value(emin.MeV());
00152 m_emax.value(emax.MeV());
00153
00154
00155 return;
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168 GModelSpectralPlaw2::GModelSpectralPlaw2(const GXmlElement& xml) :
00169 GModelSpectral()
00170 {
00171
00172 init_members();
00173
00174
00175 read(xml);
00176
00177
00178 return;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187 GModelSpectralPlaw2::GModelSpectralPlaw2(const GModelSpectralPlaw2& model) :
00188 GModelSpectral(model)
00189 {
00190
00191 init_members();
00192
00193
00194 copy_members(model);
00195
00196
00197 return;
00198 }
00199
00200
00201
00202
00203
00204 GModelSpectralPlaw2::~GModelSpectralPlaw2(void)
00205 {
00206
00207 free_members();
00208
00209
00210 return;
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 GModelSpectralPlaw2& GModelSpectralPlaw2::operator=(const GModelSpectralPlaw2& model)
00227 {
00228
00229 if (this != &model) {
00230
00231
00232 this->GModelSpectral::operator=(model);
00233
00234
00235 free_members();
00236
00237
00238 init_members();
00239
00240
00241 copy_members(model);
00242
00243 }
00244
00245
00246 return *this;
00247 }
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 void GModelSpectralPlaw2::clear(void)
00260 {
00261
00262 free_members();
00263 this->GModelSpectral::free_members();
00264
00265
00266 this->GModelSpectral::init_members();
00267 init_members();
00268
00269
00270 return;
00271 }
00272
00273
00274
00275
00276
00277
00278
00279 GModelSpectralPlaw2* GModelSpectralPlaw2::clone(void) const
00280 {
00281
00282 return new GModelSpectralPlaw2(*this);
00283 }
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 double GModelSpectralPlaw2::eval(const GEnergy& srcEng,
00320 const GTime& srcTime) const
00321 {
00322
00323 update(srcEng);
00324
00325
00326 double value = m_integral.value() * m_norm * m_power;
00327
00328
00329 #if defined(G_NAN_CHECK)
00330 if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) {
00331 std::cout << "*** ERROR: GModelSpectralPlaw2::eval";
00332 std::cout << "(srcEng=" << srcEng;
00333 std::cout << ", srcTime=" << srcTime << "):";
00334 std::cout << " NaN/Inf encountered";
00335 std::cout << " (value=" << value;
00336 std::cout << ", integral=" << integral();
00337 std::cout << ", m_norm=" << m_norm;
00338 std::cout << ", m_power=" << m_power;
00339 std::cout << ")" << std::endl;
00340 }
00341 #endif
00342
00343
00344 return value;
00345 }
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 double GModelSpectralPlaw2::eval_gradients(const GEnergy& srcEng,
00412 const GTime& srcTime)
00413 {
00414
00415 double g_integral = 0.0;
00416 double g_index = 0.0;
00417
00418
00419 update(srcEng);
00420
00421
00422 double value = m_integral.value() * m_norm * m_power;
00423
00424
00425 if (m_integral.is_free() && m_integral.factor_value() > 0.0) {
00426 g_integral = value / m_integral.factor_value();
00427 }
00428
00429
00430 if (m_index.is_free()) {
00431 g_index = value * (m_g_norm + gammalib::ln10 * srcEng.log10MeV()) *
00432 m_index.scale();
00433 }
00434
00435
00436 m_integral.factor_gradient(g_integral);
00437 m_index.factor_gradient(g_index);
00438
00439
00440 #if defined(G_NAN_CHECK)
00441 if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) {
00442 std::cout << "*** ERROR: GModelSpectralPlaw2::eval_gradients";
00443 std::cout << "(srcEng=" << srcEng;
00444 std::cout << ", srcTime=" << srcTime << "):";
00445 std::cout << " NaN/Inf encountered";
00446 std::cout << " (value=" << value;
00447 std::cout << ", integral=" << integral();
00448 std::cout << ", m_norm=" << m_norm;
00449 std::cout << ", m_power=" << m_power;
00450 std::cout << ", g_integral=" << g_integral;
00451 std::cout << ", g_index=" << g_index;
00452 std::cout << ")" << std::endl;
00453 }
00454 #endif
00455
00456
00457 return value;
00458 }
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 double GModelSpectralPlaw2::flux(const GEnergy& emin,
00479 const GEnergy& emax) const
00480 {
00481
00482 double flux = 0.0;
00483
00484
00485 if (emin < emax) {
00486
00487
00488 if (index() != -1.0) {
00489 double gamma = m_index.value() + 1.0;
00490 double pow_emin = std::pow(emin.MeV(), gamma);
00491 double pow_emax = std::pow(emax.MeV(), gamma);
00492 double pow_ref_emin = std::pow(this->emin().MeV(), gamma);
00493 double pow_ref_emax = std::pow(this->emax().MeV(), gamma);
00494 double factor = (pow_emax - pow_emin) /
00495 (pow_ref_emax - pow_ref_emin);
00496 flux = m_integral.value() * factor;
00497 }
00498
00499
00500 else {
00501 double log_emin = std::log(emin.MeV());
00502 double log_emax = std::log(emax.MeV());
00503 double log_ref_emin = std::log(this->emin().MeV());
00504 double log_ref_emax = std::log(this->emax().MeV());
00505 double factor = (log_emax - log_emin) /
00506 (log_ref_emax - log_ref_emin);
00507 flux = m_integral.value() * factor;
00508 }
00509
00510 }
00511
00512
00513 return flux;
00514 }
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534 double GModelSpectralPlaw2::eflux(const GEnergy& emin,
00535 const GEnergy& emax) const
00536 {
00537
00538 double eflux = 0.0;
00539
00540
00541 if (emin < emax) {
00542
00543
00544 double norm;
00545 if (index() != -1.0) {
00546 double gamma = m_index.value() + 1.0;
00547 double pow_ref_emin = std::pow(this->emin().MeV(), gamma);
00548 double pow_ref_emax = std::pow(this->emax().MeV(), gamma);
00549 norm = m_integral.value() * gamma / (pow_ref_emax - pow_ref_emin);
00550 }
00551 else {
00552 double log_ref_emin = std::log(this->emin().MeV());
00553 double log_ref_emax = std::log(this->emax().MeV());
00554 norm = m_integral.value() / (log_ref_emax - log_ref_emin);
00555 }
00556
00557
00558 if (index() != -2.0) {
00559 double gamma = m_index.value() + 2.0;
00560 double pow_emin = std::pow(emin.MeV(), gamma);
00561 double pow_emax = std::pow(emax.MeV(), gamma);
00562 eflux = norm / gamma * (pow_emax - pow_emin);
00563 }
00564
00565
00566 else {
00567 double log_emin = std::log(emin.MeV());
00568 double log_emax = std::log(emax.MeV());
00569 eflux = norm * (log_emax - log_emin);
00570 }
00571
00572
00573 eflux *= gammalib::MeV2erg;
00574
00575 }
00576
00577
00578 return eflux;
00579 }
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596 GEnergy GModelSpectralPlaw2::mc(const GEnergy& emin,
00597 const GEnergy& emax,
00598 const GTime& time,
00599 GRan& ran) const
00600 {
00601
00602 if (emin >= emax) {
00603 throw GException::erange_invalid(G_MC, emin.MeV(), emax.MeV(),
00604 "Minimum energy < maximum energy required.");
00605 }
00606
00607
00608 GEnergy energy;
00609
00610
00611 if (index() != -1.0) {
00612 double exponent = index() + 1.0;
00613 double e_max = std::pow(emax.MeV(), exponent);
00614 double e_min = std::pow(emin.MeV(), exponent);
00615 double u = ran.uniform();
00616 double eng = (u > 0.0)
00617 ? std::exp(std::log(u * (e_max - e_min) + e_min) / exponent)
00618 : 0.0;
00619 energy.MeV(eng);
00620 }
00621
00622
00623 else {
00624 double e_max = std::log(emax.MeV());
00625 double e_min = std::log(emin.MeV());
00626 double u = ran.uniform();
00627 double eng = std::exp(u * (e_max - e_min) + e_min);
00628 energy.MeV(eng);
00629 }
00630
00631
00632 return energy;
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 void GModelSpectralPlaw2::read(const GXmlElement& xml)
00644 {
00645
00646 const GXmlElement* integral = gammalib::xml_get_par(G_READ, xml, m_integral.name());
00647 const GXmlElement* index = gammalib::xml_get_par(G_READ, xml, m_index.name());
00648 const GXmlElement* emin = gammalib::xml_get_par(G_READ, xml, m_emin.name());
00649 const GXmlElement* emax = gammalib::xml_get_par(G_READ, xml, m_emax.name());
00650
00651
00652 m_integral.read(*integral);
00653 m_index.read(*index);
00654 m_emin.read(*emin);
00655 m_emax.read(*emax);
00656
00657
00658 return;
00659 }
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672 void GModelSpectralPlaw2::write(GXmlElement& xml) const
00673 {
00674
00675 if (xml.attribute("type") == "") {
00676 xml.attribute("type", type());
00677 }
00678
00679
00680 if (xml.attribute("type") != type()) {
00681 throw GException::model_invalid_spectral(G_WRITE, xml.attribute("type"),
00682 "Spectral model is not of type \""+type()+"\".");
00683 }
00684
00685
00686 GXmlElement* integral = gammalib::xml_need_par(G_WRITE, xml, m_integral.name());
00687 GXmlElement* index = gammalib::xml_need_par(G_WRITE, xml, m_index.name());
00688 GXmlElement* emin = gammalib::xml_need_par(G_WRITE, xml, m_emin.name());
00689 GXmlElement* emax = gammalib::xml_need_par(G_WRITE, xml, m_emax.name());
00690
00691
00692 m_integral.write(*integral);
00693 m_index.write(*index);
00694 m_emin.write(*emin);
00695 m_emax.write(*emax);
00696
00697
00698 return;
00699 }
00700
00701
00702
00703
00704
00705
00706
00707
00708 std::string GModelSpectralPlaw2::print(const GChatter& chatter) const
00709 {
00710
00711 std::string result;
00712
00713
00714 if (chatter != SILENT) {
00715
00716
00717 result.append("=== GModelSpectralPlaw2 ===");
00718
00719
00720 result.append("\n"+gammalib::parformat("Number of parameters"));
00721 result.append(gammalib::str(size()));
00722 for (int i = 0; i < size(); ++i) {
00723 result.append("\n"+m_pars[i]->print(chatter));
00724 }
00725
00726 }
00727
00728
00729 return result;
00730 }
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742 void GModelSpectralPlaw2::init_members(void)
00743 {
00744
00745 m_type = "PowerLaw";
00746
00747
00748 m_integral.clear();
00749 m_integral.name("PhotonFlux");
00750 m_integral.unit("ph/cm2/s");
00751 m_integral.scale(1.0);
00752 m_integral.value(1.0);
00753 m_integral.range(0.0, 10.0);
00754 m_integral.free();
00755 m_integral.gradient(0.0);
00756 m_integral.has_grad(true);
00757
00758
00759 m_index.clear();
00760 m_index.name("Index");
00761 m_index.scale(1.0);
00762 m_index.value(-2.0);
00763 m_index.range(-10.0,+10.0);
00764 m_index.free();
00765 m_index.gradient(0.0);
00766 m_index.has_grad(true);
00767
00768
00769 m_emin.clear();
00770 m_emin.name("LowerLimit");
00771 m_emin.unit("MeV");
00772 m_emin.scale(1.0);
00773 m_emin.value(100.0);
00774 m_emin.range(0.001, 1.0e15);
00775 m_emin.fix();
00776 m_emin.gradient(0.0);
00777 m_emin.has_grad(false);
00778
00779
00780 m_emax.clear();
00781 m_emax.name("UpperLimit");
00782 m_emax.unit("MeV");
00783 m_emax.scale(1.0);
00784 m_emax.value(500000.0);
00785 m_emin.range(0.001, 1.0e15);
00786 m_emax.fix();
00787 m_emax.gradient(0.0);
00788 m_emax.has_grad(false);
00789
00790
00791 m_pars.clear();
00792 m_pars.push_back(&m_integral);
00793 m_pars.push_back(&m_index);
00794 m_pars.push_back(&m_emin);
00795 m_pars.push_back(&m_emax);
00796
00797
00798 m_log_emin = 0.0;
00799 m_log_emax = 0.0;
00800 m_pow_emin = 0.0;
00801 m_pow_emax = 0.0;
00802 m_norm = 0.0;
00803 m_power = 0.0;
00804 m_last_integral = 0.0;
00805 m_last_index = 1000.0;
00806 m_last_emin.MeV(0.0);
00807 m_last_emax.MeV(0.0);
00808 m_last_energy.MeV(0.0);
00809 m_last_value = 0.0;
00810 m_last_g_integral = 0.0;
00811 m_last_g_index = 0.0;
00812
00813
00814 return;
00815 }
00816
00817
00818
00819
00820
00821
00822
00823 void GModelSpectralPlaw2::copy_members(const GModelSpectralPlaw2& model)
00824 {
00825
00826 m_type = model.m_type;
00827 m_integral = model.m_integral;
00828 m_index = model.m_index;
00829 m_emin = model.m_emin;
00830 m_emax = model.m_emax;
00831
00832
00833 m_pars.clear();
00834 m_pars.push_back(&m_integral);
00835 m_pars.push_back(&m_index);
00836 m_pars.push_back(&m_emin);
00837 m_pars.push_back(&m_emax);
00838
00839
00840 m_log_emin = model.m_log_emin;
00841 m_log_emax = model.m_log_emax;
00842 m_pow_emin = model.m_pow_emin;
00843 m_pow_emax = model.m_pow_emax;
00844 m_norm = model.m_norm;
00845 m_power = model.m_power;
00846 m_last_integral = model.m_last_integral;
00847 m_last_index = model.m_last_index;
00848 m_last_emin = model.m_last_emin;
00849 m_last_emax = model.m_last_emax;
00850 m_last_energy = model.m_last_energy;
00851 m_last_value = model.m_last_value;
00852 m_last_g_integral = model.m_last_g_integral;
00853 m_last_g_index = model.m_last_g_index;
00854
00855
00856 return;
00857 }
00858
00859
00860
00861
00862
00863 void GModelSpectralPlaw2::free_members(void)
00864 {
00865
00866 return;
00867 }
00868
00869
00870
00871
00872
00873
00874
00875 void GModelSpectralPlaw2::update(const GEnergy& srcEng) const
00876 {
00877
00878 double gamma = index() + 1.0;
00879
00880
00881 if (index() != m_last_index) {
00882
00883
00884 m_last_index = index();
00885
00886
00887 if (emin() != m_last_emin || emax() != m_last_emax) {
00888 m_log_emin = std::log(emin().MeV());
00889 m_last_emin = emin();
00890 m_log_emax = std::log(emax().MeV());
00891 m_last_emax = emax();
00892 }
00893
00894
00895 if (gamma != 0.0) {
00896 m_pow_emin = std::pow(emin().MeV(), gamma);
00897 m_pow_emax = std::pow(emax().MeV(), gamma);
00898 double d = m_pow_emax - m_pow_emin;
00899 m_norm = gamma / d;
00900 m_g_norm = 1.0/gamma -
00901 (m_pow_emax*m_log_emax - m_pow_emin*m_log_emin)/d;
00902 }
00903 else {
00904 m_norm = 1.0 / (m_log_emax - m_log_emin);
00905 m_g_norm = 0.0;
00906 }
00907
00908
00909 m_power = std::pow(srcEng.MeV(), index());
00910 m_last_energy = srcEng;
00911
00912 }
00913
00914
00915 else {
00916
00917
00918 if (emin() != m_last_emin || emax() != m_last_emax) {
00919
00920
00921 m_log_emin = std::log(emin().MeV());
00922 m_last_emin = emin();
00923 m_log_emax = std::log(emax().MeV());
00924 m_last_emax = emax();
00925
00926
00927 if (gamma != 0.0) {
00928 m_pow_emin = std::pow(emin().MeV(), gamma);
00929 m_pow_emax = std::pow(emax().MeV(), gamma);
00930 double d = m_pow_emax - m_pow_emin;
00931 m_norm = gamma / d;
00932 m_g_norm = 1.0/gamma -
00933 (m_pow_emax*m_log_emax - m_pow_emin*m_log_emin)/d;
00934 }
00935 else {
00936 m_norm = 1.0 / (m_log_emax - m_log_emin);
00937 m_g_norm = 0.0;
00938 }
00939
00940 }
00941
00942
00943 if (srcEng != m_last_energy) {
00944 m_power = std::pow(srcEng.MeV(), index());
00945 m_last_energy = srcEng;
00946 }
00947
00948 }
00949
00950
00951 return;
00952 }