00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef O2SCL_NUCLEAR_MASS_H
00024 #define O2SCL_NUCLEAR_MASS_H
00025
00026 #include <cmath>
00027 #include <string>
00028 #include <map>
00029 #include <o2scl/nucleus.h>
00030 #include <o2scl/constants.h>
00031 #include <o2scl/base_ioc.h>
00032
00033 #ifndef DOXYGENP
00034 namespace o2scl {
00035 #endif
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 class nuclear_mass {
00107 public:
00108
00109 nuclear_mass();
00110
00111 virtual ~nuclear_mass() {};
00112
00113
00114
00115
00116
00117 virtual bool is_included(int Z, int N) {
00118 return true;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 int get_nucleus(int Z, int N, nucleus &n) {
00130 n.Z=Z;
00131 n.N=N;
00132 n.A=Z+N;
00133 n.mex=mass_excess(Z,N)/o2scl_const::hc_mev_fm;
00134 n.m=n.mex+((Z+N)*o2scl_fm::mass_amu-Z*o2scl_fm::mass_electron);
00135 n.ms=n.mex+((Z+N)*o2scl_fm::mass_amu-Z*o2scl_fm::mass_electron);
00136 n.be=(n.m-N*o2scl_fm::mass_neutron-Z*o2scl_fm::mass_proton);
00137 if (n.A%2==0) n.g=1.0;
00138 else n.g=2.0;
00139 return 0;
00140 }
00141
00142
00143 virtual double mass_excess(int Z, int N) {
00144 if (form_type==cont_type) {
00145 return mass_excess_d(Z,N);
00146 }
00147 set_err("Using base class version of mass_excess().",gsl_nobase);
00148 return 0.0;
00149 }
00150
00151
00152
00153 virtual double mass_excess_d(double Z, double N) {
00154 if (form_type==disc_type) {
00155 int Z1=(int)Z;
00156 int N1=(int)N;
00157 double mz1n1=mass_excess(Z1,N1);
00158 double mz1n2=mass_excess(Z1,N1+1);
00159 double mz2n1=mass_excess(Z1+1,N1);
00160 double mz2n2=mass_excess(Z1+1,N1+1);
00161 double mz1=mz1n1+(N-N1)*(mz1n2-mz1n1);
00162 double mz2=mz2n1+(N-N1)*(mz2n2-mz2n1);
00163 return mz1+(Z-Z1)*(mz2-mz1);
00164 }
00165 set_err("Using base class version of mass_excess_d().",gsl_nobase);
00166 return 0.0;
00167 }
00168
00169
00170
00171
00172
00173
00174
00175
00176 virtual double binding_energy(int Z, int N) {
00177 return (mass_excess(Z,N)+
00178 ((Z+N)*o2scl_fm::mass_amu-Z*o2scl_fm::mass_electron-
00179 N*o2scl_fm::mass_neutron-Z*o2scl_fm::mass_proton)*
00180 o2scl_const::hc_mev_fm);
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
00190 virtual double binding_energy_d(double Z, double N) {
00191 return (mass_excess_d(Z,N)+
00192 ((Z+N)*o2scl_fm::mass_amu-Z*o2scl_fm::mass_electron-
00193 N*o2scl_fm::mass_neutron-Z*o2scl_fm::mass_proton)*
00194 o2scl_const::hc_mev_fm);
00195 }
00196
00197
00198
00199
00200 virtual double total_mass(int Z, int N) {
00201 return (mass_excess(Z,N)+((Z+N)*o2scl_fm::mass_amu-
00202 Z*o2scl_fm::mass_electron)*
00203 o2scl_const::hc_mev_fm);
00204 }
00205
00206
00207
00208
00209 virtual double total_mass_d(double Z, double N) {
00210 return (mass_excess_d(Z,N)+((Z+N)*o2scl_fm::mass_amu-
00211 Z*o2scl_fm::mass_electron)*
00212 o2scl_const::hc_mev_fm);
00213 }
00214
00215
00216 int eltoZ(std::string el) {
00217 return element_table.find(el)->second;
00218 }
00219
00220
00221 std::string Ztoel(int Z) {
00222 return element_list[Z];
00223 }
00224
00225
00226
00227
00228
00229
00230
00231 int parse_elstring(std::string ela, int &Z, int &N, int &A) {
00232 if (ela.length()<2) {
00233 set_err_ret
00234 ("Element name too short in nuclear_mass::parse_elstring().",
00235 gsl_efailed);
00236 }
00237 if (ela.length()>3 && isalpha(ela[2])) {
00238 std::string el=ela.substr(0,3);
00239 Z=eltoZ(el);
00240 A=stoi(ela.substr(3,ela.length()-2));
00241 N=A-Z;
00242 return 0;
00243 }
00244 if (ela.length()>2 && isalpha(ela[1])) {
00245 std::string el=ela.substr(0,2);
00246 Z=eltoZ(el);
00247 A=stoi(ela.substr(2,ela.length()-2));
00248 N=A-Z;
00249 return 0;
00250 }
00251 std::string el=ela.substr(0,1);
00252 Z=eltoZ(el);
00253 A=stoi(ela.substr(1,ela.length()-1));
00254 N=A-Z;
00255 return 0;
00256 }
00257
00258 #ifndef DOXYGEN_INTERNAL
00259
00260 protected:
00261
00262
00263 struct string_less_than {
00264 bool operator()(const std::string s1, const std::string s2) const {
00265 return s1<s2;
00266 }
00267 };
00268
00269
00270 static const int nelements=119;
00271
00272
00273 std::map<std::string,int,string_less_than> element_table;
00274
00275
00276 typedef std::map<std::string,int,string_less_than>::iterator table_it;
00277
00278
00279 std::string element_list[nelements];
00280
00281
00282
00283
00284
00285
00286 int form_type;
00287 static const int cont_type=1;
00288 static const int disc_type=2;
00289
00290
00291 #endif
00292
00293 };
00294
00295
00296
00297
00298 class nuclear_mass_fit : public nuclear_mass {
00299
00300 public:
00301
00302
00303 size_t nfit;
00304
00305
00306 virtual int fit_fun(size_t nv, const ovector_view &x) {
00307 return 0;
00308 }
00309
00310
00311 virtual int guess_fun(size_t nv, ovector_view &x) {
00312 return 0;
00313 }
00314
00315 };
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 class semi_empirical_mass : public nuclear_mass_fit {
00326
00327 public:
00328
00329
00330 double B;
00331
00332
00333 double Sv;
00334
00335
00336 double Ss;
00337
00338
00339 double Ec;
00340
00341
00342 double Epair;
00343
00344 semi_empirical_mass() {
00345 B=-16.0;
00346 Ss=18.0;
00347 Ec=0.7;
00348 Sv=23.7;
00349 Epair=13.0;
00350 nfit=5;
00351 form_type=cont_type;
00352 }
00353
00354
00355 virtual double mass_excess_d(double Z, double N) {
00356 double A=Z+N, cA=cbrt(A);
00357 double EoA=B+Ss/cA+Ec*Z*Z/cA/A+Sv*pow(1.0-2.0*Z/A,2.0);
00358 if (((int)(A-Z+0.01))%2==0 && ((int)(Z+0.01))%2==0) {
00359 EoA-=Epair/pow(A,1.5);
00360 } else if (((int)(A-Z+0.01))%2==1 && ((int)(Z+0.01))%2==1) {
00361 EoA+=Epair/pow(A,1.5);
00362 }
00363 double ret=EoA*A+Z*(o2scl_fm::mass_proton+o2scl_fm::mass_electron)*
00364 o2scl_const::hc_mev_fm+N*o2scl_fm::mass_neutron*
00365 o2scl_const::hc_mev_fm-A*o2scl_fm::mass_amu*o2scl_const::hc_mev_fm;
00366 return ret;
00367 }
00368
00369
00370 virtual int fit_fun(size_t nv, const ovector_view &x) {
00371 B=-x[0]; Sv=x[1]; Ss=x[2]; Ec=x[3]; Epair=x[4];
00372 return 0;
00373 }
00374
00375
00376 virtual int guess_fun(size_t nv, ovector_view &x) {
00377 x[0]=-B; x[1]=Sv; x[2]=Ss; x[3]=Ec; x[4]=Epair;
00378 return 0;
00379 }
00380
00381 };
00382
00383
00384
00385
00386 typedef struct mnms95_mass_entry_s {
00387
00388
00389 int N;
00390
00391
00392 int Z;
00393
00394
00395 int A;
00396
00397
00398
00399
00400
00401 double eps2;
00402
00403 double eps3;
00404
00405 double eps4;
00406
00407 double eps6;
00408
00409 double eps6sym;
00410
00411
00412
00413
00414
00415
00416 double beta2;
00417
00418 double beta3;
00419
00420 double beta4;
00421
00422 double beta6;
00423
00424
00425
00426 double Emic;
00427
00428
00429 double Mth;
00430
00431
00432 double Mexp;
00433
00434
00435 double sigmaexp;
00436
00437
00438 double EmicFL;
00439
00440
00441 double MthFL;
00442
00443 } mnms95_mass_entry;
00444
00445 template<> int io_tlate<mnms95_mass_entry>::input
00446 (cinput *co, in_file_format *ins, mnms95_mass_entry *t);
00447 template<> int io_tlate<mnms95_mass_entry>::output
00448 (coutput *co, out_file_format *outs, mnms95_mass_entry *t);
00449 template<> const char *io_tlate<mnms95_mass_entry>::type();
00450
00451 typedef io_tlate<mnms95_mass_entry> mnms95_mass_entry_io_type;
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468 class mnms95_mass : public nuclear_mass {
00469 public:
00470
00471 mnms95_mass();
00472
00473
00474
00475
00476
00477 virtual bool is_included(int Z, int N);
00478
00479
00480 virtual double mass_excess(int Z, int N) {
00481 mnms95_mass_entry ret;
00482 ret=get_ZN(Z,N);
00483 if (ret.Z==0 && ret.N==0) return 0.0;
00484 return ret.Mth;
00485 }
00486
00487
00488
00489
00490
00491
00492
00493
00494 mnms95_mass_entry get_ZN(int l_Z, int l_N);
00495
00496
00497 bool is_loaded() { return loaded; };
00498
00499
00500 int n;
00501
00502
00503 mnms95_mass_entry *mass;
00504
00505 #ifndef DOXYGEN_INTERNAL
00506
00507 protected:
00508
00509
00510 bool loaded;
00511
00512
00513 int last;
00514
00515 #endif
00516
00517 };
00518
00519
00520 class mnms95_mass_exp : public mnms95_mass {
00521
00522 public:
00523
00524
00525
00526
00527
00528 virtual bool is_included(int Z, int N);
00529
00530
00531 virtual double mass_excess(int Z, int N) {
00532 mnms95_mass_entry ret;
00533 ret=get_ZN(Z,N);
00534 if (ret.Z==0 && ret.N==0) return 0.0;
00535 return ret.Mexp;
00536 }
00537
00538 };
00539
00540
00541
00542
00543 typedef struct ame_entry_s {
00544
00545
00546 int NMZ;
00547
00548
00549 int N;
00550
00551
00552 int Z;
00553
00554
00555 int A;
00556
00557
00558 std::string el;
00559
00560
00561 std::string orig;
00562
00563
00564 double mass;
00565
00566
00567 double dmass;
00568
00569
00570 double be;
00571
00572
00573 double dbe;
00574
00575
00576 double beoa;
00577
00578
00579 double dbeoa;
00580
00581
00582 std::string bdmode;
00583
00584
00585 double bde;
00586
00587
00588 double dbde;
00589
00590
00591 int A2;
00592
00593
00594 double amass;
00595
00596
00597 double damass;
00598
00599 } ame_entry;
00600
00601
00602
00603 class ame_entry95_io_type : public io_tlate<ame_entry> {
00604 public:
00605 int input(cinput *co, in_file_format *ins, ame_entry *t);
00606 int output(coutput *co, out_file_format *outs, ame_entry *t);
00607 virtual const char *type();
00608 };
00609
00610
00611
00612 class ame_entry03_io_type : public io_tlate<ame_entry> {
00613 public:
00614 int input(cinput *co, in_file_format *ins, ame_entry *t);
00615 int output(coutput *co, out_file_format *outs, ame_entry *t);
00616 virtual const char *type();
00617 };
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660 class ame_mass : public nuclear_mass {
00661 public:
00662
00663
00664 ame_mass(std::string version="");
00665
00666
00667
00668
00669
00670 virtual bool is_included(int Z, int N);
00671
00672
00673 virtual double mass_excess(int Z, int N) {
00674 ame_entry ret;
00675 ret=get_ZN(Z,N);
00676 if (ret.Z==0 && ret.N==0) return 0.0;
00677 return ret.mass/1.0e3;
00678 }
00679
00680
00681 ame_entry get_ZN(int l_Z, int l_N);
00682
00683
00684 ame_entry get_ZA(int l_Z, int l_A);
00685
00686
00687 ame_entry get_elA(std::string l_el, int l_A);
00688
00689
00690 ame_entry get(std::string nucleus);
00691
00692
00693 int n;
00694
00695
00696 std::string *short_names;
00697
00698
00699 std::string *col_names;
00700
00701
00702 std::string reference;
00703
00704
00705 ame_entry *mass;
00706
00707
00708 bool is_loaded() { return loaded; }
00709
00710 #ifndef DOXYGEN_INTERNAL
00711
00712 protected:
00713
00714
00715 bool loaded;
00716
00717 #endif
00718
00719 };
00720
00721 #ifndef DOXYGENP
00722 }
00723 #endif
00724
00725 #endif