00001
00002
00003
00004 #include <fstream.h>
00005 #include "single_star.h"
00006 #include "proto_star.h"
00007
00008
00009
00010 #include "SPZDCH_star.h"
00011
00012 #define REPORT_MASS_TRANSFER_TIMESCALE true
00013
00014 single_star * new_single_star(stellar_type type,
00015 int id,
00016 real t_cur,
00017 real t_rel,
00018 real m_rel,
00019 real m_tot,
00020 real m_core,
00021 real co_core,
00022 real p_rot,
00023 real b_fld,
00024 node* n)
00025 {
00026
00027
00028
00029
00030 single_star* element = 0;
00031 switch(type) {
00032 case SPZDCH_Star: element = new SPZDCH_star(n);
00033 break;
00034 case Proto_Star: element = new proto_star(n);
00035 break;
00036 case Planet:
00037 case Brown_Dwarf: element = new brown_dwarf(n);
00038 break;
00039 case Main_Sequence: element = new main_sequence(n);
00040 break;
00041 case Hertzsprung_Gap: element = new hertzsprung_gap(n);
00042 break;
00043 case Sub_Giant: element = new sub_giant(n);
00044 break;
00045 case Horizontal_Branch: element = new horizontal_branch(n);
00046 break;
00047 case Super_Giant: element = new super_giant(n);
00048 break;
00049 case Carbon_Star:
00050 case Helium_Star:
00051 case Helium_Giant: element = new helium_star(n);
00052 break;
00053 case Hyper_Giant: element = new hyper_giant(n);
00054 break;
00055 case Helium_Dwarf:
00056 case Carbon_Dwarf:
00057 case Oxygen_Dwarf: element = new white_dwarf(n);
00058 break;
00059 case Thorn_Zytkow: element = new thorne_zytkow(n);
00060 break;
00061 case Xray_Pulsar:
00062 case Radio_Pulsar:
00063 case Neutron_Star: element = new neutron_star(n);
00064 element->set_rotation_period(p_rot);
00065 element->set_magnetic_field(b_fld);
00066 break;
00067 case Black_Hole: element = new black_hole(n);
00068 break;
00069 case Disintegrated: element = new disintegrated(n);
00070 break;
00071
00072 default: cerr << "No default stellar type in new_single_star()"<<endl;
00073 exit(1);
00074
00075 }
00076
00077 element->initialize(id, t_cur, t_rel, m_rel, m_tot, m_core, co_core);
00078
00079 element->post_constructor();
00080
00081 return element;
00082 }
00083
00084 single_star::single_star(node* n) : star(n) {
00085
00086 star_type = NAS;
00087 for (int i=NAC; i<no_of_spec_type; i++)
00088 spec_type[i] = NAC;
00089 current_time=relative_age=0;
00090 last_update_age = next_update_age=0;
00091 relative_mass = accreted_mass=0;
00092 envelope_mass=core_mass=0;
00093 core_radius=effective_radius=radius=0;
00094 COcore_mass = 0;
00095 luminosity=0;
00096 velocity=0;
00097 wind_constant=0;
00098 magnetic_field = rotation_period = 0;
00099 birth_mass=0;
00100 }
00101
00102
00103 single_star::single_star(single_star & rv) : star(rv) {
00104
00105 identity = rv.identity;
00106
00107 for (int i=NAC; i<no_of_spec_type; i++)
00108 spec_type[i] = rv.spec_type[i];
00109
00110
00111 current_time = rv.current_time;
00112 relative_age = rv.relative_age;
00113 relative_mass = rv.relative_mass;
00114 envelope_mass = rv.envelope_mass;
00115 core_mass = rv.core_mass;
00116 COcore_mass = rv.COcore_mass;
00117
00118 core_radius = rv.core_radius;
00119 radius = rv.radius;
00120 luminosity = rv.luminosity;
00121 effective_radius = rv.effective_radius;
00122 last_update_age = rv.last_update_age;
00123 next_update_age = rv.next_update_age;
00124 velocity = rv.velocity;
00125 wind_constant = rv.wind_constant;
00126 accreted_mass = rv.accreted_mass;
00127 magnetic_field = rv.magnetic_field;
00128 rotation_period = rv.rotation_period;
00129 birth_mass = rv.birth_mass;
00130
00131
00132 previous.current_time = rv.previous.current_time;
00133 previous.last_update_age = rv.previous.last_update_age;
00134 previous.next_update_age = rv.previous.next_update_age;
00135 previous.relative_age = rv.previous.relative_age;
00136 previous.relative_mass = rv.previous.relative_mass;
00137 previous.envelope_mass = rv.previous.envelope_mass;
00138 previous.core_mass = rv.previous.core_mass;
00139 previous.COcore_mass = rv.previous.COcore_mass;
00140
00141 previous.radius = rv.previous.radius;
00142 previous.effective_radius= rv.previous.effective_radius;
00143 previous.magnetic_field = rv.previous.magnetic_field;
00144 previous.rotation_period = rv.previous.rotation_period;
00145 previous.birth_mass = rv.previous.birth_mass;
00146
00147 }
00148
00149 void single_star::post_constructor() {
00150
00151
00152 update_wind_constant();
00153
00154
00155
00156
00157
00158 if (is_binary_component())
00159 get_binary()->refresh_memory();
00160 else
00161 refresh_memory();
00162
00163
00164 if (is_binary_component() && get_binary()->get_bin_type()==Detached)
00165 get_binary()->set_first_contact(false);
00166
00167 if (is_binary_component())
00168 get_binary()->dump("SeBa.data", true);
00169 else
00170
00171
00172
00173
00174
00175
00176
00177 if (remnant()) {
00178 if (is_binary_component())
00179 get_binary()->dump("binev.data", false);
00180 else
00181 dump("binev.data", false);
00182 }
00183
00184 }
00185
00186 void single_star::initialize(int id, real t_cur,
00187 real t_rel, real m_rel, real m_tot,
00188 real m_core, real co_core) {
00189
00190
00191
00192
00193 real m_env = m_tot - m_core;
00194 if (m_rel<=0 || m_rel>cnsts.parameters(maximum_main_sequence)) {
00195 cerr << "Mass of initial star is prefered to be "
00196 << "\nwithin reasonable limits <0, "
00197 << cnsts.parameters(maximum_main_sequence)
00198 << "] \nbut found (mass = " << m_rel << ")" << endl;
00199 if (m_rel<=0)
00200 exit (-1);
00201 }
00202
00203 identity = id;
00204 luminosity = 0.01;
00205 current_time = t_cur;
00206 relative_age = t_rel;
00207 relative_mass = max(m_rel, m_env+m_core);
00208 previous.envelope_mass = envelope_mass = m_env;
00209 core_mass = m_core;
00210 COcore_mass = co_core;
00211
00212 instantaneous_element();
00213
00214
00215
00216 update_wind_constant();
00217 adjust_next_update_age();
00218
00219
00220 instantaneous_element();
00221
00222 update();
00223 }
00224
00225
00226
00227
00228 real single_star::helium_core_radius() {
00229
00230
00231 if (core_mass==0) {
00232 cerr << "WARNING single_star::helium_core_radius():" << endl;
00233 cerr << " core_radius == 0" << endl;
00234 cerr << " action: return 0;" << endl;
00235 return 0;
00236 }
00237
00238 real r_he_core;
00239 real tmp = log10(core_mass)
00240 * (0.4509 - 0.1085*log10(core_mass)) + 4.7143;
00241 real lum = 8.33*tmp - 36.8;
00242 tmp = 1.e-3*pow(10., tmp);
00243 lum = pow(10., lum);
00244
00245
00246
00247
00248
00249 real fraction =1.;
00250 r_he_core = fraction*33.45*sqrt(lum)/pow(tmp, 2);
00251
00252 return min(radius, r_he_core);
00253 }
00254
00255 real single_star::main_sequence_time(const real mass) {
00256
00257 real t_ms = (2550. + 667.*pow(mass,2.5) + pow(mass,4.5) )
00258 / (0.0327*pow(mass,1.5) + 0.346*pow(mass,4.5));
00259
00260 return t_ms;
00261 }
00262
00263 real single_star::main_sequence_time() {
00264
00265 real t_ms = (2550. + 667.*pow(relative_mass,2.5)
00266 + pow(relative_mass,4.5) )
00267 / (0.0327*pow(relative_mass,1.5)
00268 + 0.346*pow(relative_mass,4.5));
00269
00270 return t_ms;
00271 }
00272
00273 real single_star::hertzsprung_gap_time(const real mass, const real t_ms) {
00274
00275 return 0.54*t_ms/(mass*(mass - 2.1) + 23.3);
00276 }
00277
00278 real single_star::hertzsprung_gap_time(const real t_ms) {
00279
00280 return 0.54*t_ms/(relative_mass*(relative_mass - 2.1) + 23.3);
00281 }
00282
00283 real single_star::helium_giant_time(const real mass, const real t_ms) {
00284
00285 real l_bms = base_main_sequence_luminosity(mass);
00286 real l_he = helium_giant_luminosity(mass);
00287
00288 return t_ms*l_bms/(l_he*(pow(mass, 0.42) + 0.8));
00289 }
00290
00291 real single_star::helium_giant_time(const real t_ms) {
00292
00293 real l_bms = base_main_sequence_luminosity();
00294 real l_he = helium_giant_luminosity();
00295
00296 return t_ms*l_bms/(l_he*(pow(relative_mass, 0.42) + 0.8));
00297 }
00298
00299 real single_star::base_giant_branch_time(const real mass, const real t_ms) {
00300
00301 real t_g = 0.15 * t_ms;
00302 real l_g = giant_luminosity(mass);
00303
00304 real l_bagb = base_agb_luminosity(l_g, mass);
00305
00306 return t_g - t_g*pow((l_g/l_bagb), 0.855);
00307 }
00308
00309 real single_star::base_giant_branch_time(const real t_ms) {
00310
00311 real t_g = 0.15 * t_ms;
00312 real l_g = giant_luminosity();
00313 real l_bagb = base_agb_luminosity(l_g);
00314
00315 return t_g - t_g*pow((l_g/l_bagb), 0.855);
00316 }
00317
00318 real single_star::base_giant_time(const real mass, const real t_ms) {
00319
00320 real t_gs = 0.15*t_ms;
00321 real l_g = giant_luminosity(mass);
00322 real l_agb = agb_luminosity(mass);
00323
00324 return t_gs*pow(l_g/l_agb, 0.855);
00325 }
00326
00327 real single_star::base_giant_time(const real t_ms) {
00328
00329 real t_gs = 0.15*t_ms;
00330 real l_g = giant_luminosity();
00331 real l_agb = agb_luminosity();
00332
00333 return t_gs*pow(l_g/l_agb, 0.855);
00334 }
00335
00336 real single_star::nucleair_evolution_time(const real mass) {
00337
00338 real l_g = giant_luminosity(mass);
00339
00340 real l_bagb = base_agb_luminosity(l_g, mass);
00341 real l_agb = agb_luminosity(mass);
00342
00343 real t_ms = main_sequence_time(mass);
00344 real t_g = 0.15*t_ms;
00345 real t_hg = hertzsprung_gap_time(mass, t_ms);
00346 real t_bgb = t_g - t_g*pow((l_g/l_bagb), 0.855);
00347 real t_he = helium_giant_time(mass, t_ms);
00348 real t_gs = t_g;
00349 real t_b = t_gs*pow(l_g/l_agb, 0.855);
00350 real t_agb = t_gs - t_bgb - t_b;
00351
00352 return t_ms + t_hg + t_bgb + t_he + t_agb;
00353 }
00354
00355
00356 real single_star::nucleair_evolution_time() {
00357
00358 real l_g = giant_luminosity();
00359 real l_bagb = base_agb_luminosity(l_g);
00360 real l_agb = agb_luminosity();
00361
00362 real t_ms = main_sequence_time();
00363 real t_g = 0.15*t_ms;
00364 real t_hg = hertzsprung_gap_time(t_ms);
00365 real t_bgb = t_g - t_g*pow((l_g/l_bagb), 0.855);
00366 real t_he = helium_giant_time(t_ms);
00367 real t_gs = t_g;
00368 real t_b = t_gs*pow(l_g/l_agb, 0.855);
00369 real t_agb = t_gs - t_bgb - t_b;
00370
00371 return t_ms + t_hg + t_bgb + t_he + t_agb;
00372 }
00373
00374 real single_star::base_main_sequence_luminosity() {
00375
00376 real l_bms;
00377 if (relative_mass<=1.093) {
00378 l_bms = (1.107*pow(relative_mass, 3.)
00379 + 240.7*pow(relative_mass, 9.))
00380 / (1. + 281.9*pow(relative_mass, 4.));
00381 }
00382 else {
00383 l_bms = (13990.*pow(relative_mass, 5.))
00384 / (pow(relative_mass, 4.)
00385 + 2151.*pow(relative_mass, 2)
00386 + 3908.*relative_mass +9536.);
00387 }
00388
00389 return l_bms;
00390 }
00391
00392 real single_star::base_main_sequence_luminosity(const real mass) {
00393
00394 real l_bms;
00395 if (mass<=1.093) {
00396 l_bms = (1.107*pow(mass, 3.)+ 240.7*pow(mass, 9.))
00397 / (1. + 281.9*pow(mass, 4.));
00398 }
00399 else {
00400 l_bms = (13990.*pow(mass, 5.))
00401 / (pow(mass, 4.) + 2151.*pow(mass, 2)+3908.*mass +9536.);
00402 }
00403
00404 return l_bms;
00405 }
00406
00407 real single_star::giant_luminosity(const real mass) {
00408
00409 real l_g = (2.15 + 0.22*pow(mass, 3.))*pow(mass, 2)
00410 / (5.0e-6*pow(mass, 4.)+1.4e-2*mass*mass + 1.);
00411
00412 return l_g;
00413 }
00414
00415 real single_star::giant_luminosity() {
00416
00417 real l_g = (2.15 + 0.22*pow(relative_mass, 3.))
00418 * pow(relative_mass, 2)
00419 / (5.0e-6*pow(relative_mass, 4.)
00420 + 1.4e-2*relative_mass*relative_mass + 1.);
00421
00422 return l_g;
00423 }
00424
00425 real single_star::helium_giant_luminosity(const real mass) {
00426
00427
00428
00429
00430
00431
00432
00433 real l_g = base_giant_branch_luminosity(mass);
00434 real l_HeI = base_agb_luminosity(l_g, mass);
00435 real l_He = 49*pow(mass, 0.364) + 0.86*pow(mass, 4.);
00436
00437 return min(l_He, l_HeI);
00438 }
00439
00440 real single_star::helium_giant_luminosity() {
00441
00442
00443
00444
00445
00446
00447
00448 real l_g = base_giant_branch_luminosity(relative_mass);
00449 real l_HeI = base_agb_luminosity(l_g, relative_mass);
00450 real l_He = 49*pow(relative_mass, 0.364)
00451 + 0.86*pow(relative_mass, 4.);
00452
00453 return min(l_He, l_HeI);
00454
00455 }
00456
00457 real single_star::base_giant_branch_luminosity(const real mass) {
00458
00459 real kappa, lambda;
00460 real log_mass = log10(mass);
00461
00462 if (mass<1.334) {
00463 kappa = 0.2594 + 0.1348*log_mass;
00464 lambda = 0.144 - 0.8333*log_mass;
00465 }
00466 else {
00467 kappa = 0.092088 + 0.059338*log_mass;
00468 lambda = -0.05713 + log_mass*(0.3756 -0.1744);
00469 }
00470
00471 real l_bms = base_main_sequence_luminosity(mass);
00472
00473 return l_bms*pow(10., kappa + lambda);
00474 }
00475
00476
00477 real single_star::base_giant_branch_luminosity() {
00478
00479 real kappa, lambda;
00480 real log_mass = log10(relative_mass);
00481
00482 if (relative_mass<1.334) {
00483 kappa = 0.2594 + 0.1348*log_mass;
00484 lambda = 0.144 - 0.8333*log_mass;
00485 }
00486 else {
00487 kappa = 0.092088 + 0.059338*log_mass;
00488 lambda = -0.05713 + log_mass*(0.3756 -0.1744);
00489 }
00490
00491 real l_bms = base_main_sequence_luminosity();
00492
00493 return l_bms*pow(10., kappa + lambda);
00494 }
00495
00496 real single_star::base_agb_luminosity(const real l_g) {
00497
00498
00499
00500
00501
00502 real l_agb=2454.7;
00503 if (relative_mass >
00504 cnsts.parameters(upper_ZAMS_mass_for_degenerate_core))
00505 l_agb = 6.5*pow(min(relative_mass, 20.), 3.25);
00506
00507 return max(l_agb, l_g);
00508 }
00509
00510 real single_star::base_agb_luminosity(const real l_g,
00511 const real mass) {
00512
00513 real l_agb=2454.7;
00514 if (mass >
00515 cnsts.parameters(upper_ZAMS_mass_for_degenerate_core))
00516 l_agb = 6.5*pow(min(mass, 20.), 3.25);
00517
00518 return max(l_agb, l_g);
00519 }
00520
00521 real single_star::agb_luminosity(const real mass) {
00522
00523 return mass*(4.0e3 + 5.0e2*mass);
00524 }
00525
00526 real single_star::agb_luminosity() {
00527
00528 return relative_mass*(4.0e3 + 5.0e2*relative_mass);
00529 }
00530
00531 real single_star::maximum_luminosity(const real mass) {
00532
00533 return 4000*mass + 500*pow(mass,2);
00534 }
00535
00536 real single_star::maximum_luminosity() {
00537 return 4000*relative_mass + 500*pow(relative_mass,2);
00538 }
00539
00540
00541
00542
00543 real single_star::helium_time() {
00544
00545 real m = get_total_mass();
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 real t_he = 0;
00556 if (m<=0.7)
00557 t_he = 10.76*pow(m, -3.75);
00558 else if(m<=1.6)
00559 t_he = 17.1*pow(m, -2.45);
00560 else if(m<=4.8)
00561 t_he = 11.48*pow(m, -1.6);
00562 else
00563 t_he = 2.37*pow(m, -0.6);
00564
00565 return t_he;
00566 }
00567
00568 real single_star::temperature() {
00569
00570
00571
00572
00573
00574
00575
00576
00577 real T_eff = cnsts.parameters(Tsun)
00578 * pow(luminosity/pow(effective_radius, 2), 0.25);
00579
00580 return T_eff;
00581 }
00582
00583 real single_star::magnitude() {
00584
00585 return -2.5*log10(luminosity) + 4.75 - bolometric_correction();
00586 }
00587
00588
00589
00590
00591
00592 real single_star::bolometric_correction() {
00593
00594
00595
00596
00597 real temp_in_kK = 0.001 * temperature();
00598 real bc;
00599
00600 if (temp_in_kK < 4.195)
00601 bc = 2.5*log10((1.724e-7*pow(temp_in_kK,11.) + 1.925e-2)
00602 / (1. + 1.884e-9*pow(temp_in_kK,14.)));
00603 else if (temp_in_kK >= 4.195 &&
00604 temp_in_kK <= 10.89)
00605 bc = 2.5*log10((7.56e-2*pow(temp_in_kK,1.5))
00606 / (1. + 6.358e-5*pow(temp_in_kK, 4.5)));
00607 else
00608 bc = 2.5*log10((2728/pow(temp_in_kK,3.5) + 1.878e-2*temp_in_kK)
00609 /(1. + 5.362e-5*pow(temp_in_kK,3.5)));
00610
00611 return bc;
00612 }
00613
00614
00615
00616 real single_star::wind_velocity() {
00617
00618 real v_esc2 = cnsts.physics(G)
00619 * cnsts.parameters(solar_mass)*get_total_mass()
00620 / (effective_radius*cnsts.parameters(solar_radius));
00621 real v_wind = 2.5*sqrt(v_esc2)/cnsts.physics(km_per_s);
00622
00623 return v_wind;
00624 }
00625
00626 real single_star::kelvin_helmholds_timescale() {
00627
00628
00629
00630
00631 return 31.56*pow(relative_mass,2.)/(radius*luminosity);
00632 }
00633
00634 real single_star::nucleair_evolution_timescale() {
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656 return 0.1*main_sequence_time();
00657
00658 }
00659
00660 real single_star::dynamic_timescale() {
00661
00662 return 5.08e-11*sqrt(pow(radius, 3.)/relative_mass);
00663 }
00664
00665
00666 bool single_star::low_mass_star() {
00667
00668 bool is_low_mass_star = false;
00669
00670 if (!remnant()) {
00671 if(relative_mass <= cnsts.parameters(low_mass_star_mass_limit))
00672 is_low_mass_star = true;
00673 }
00674 else if (get_total_mass() <=
00675 cnsts.parameters(low_mass_star_mass_limit)) {
00676 is_low_mass_star = true;
00677 }
00678
00679 return is_low_mass_star;
00680 }
00681
00682 bool single_star::medium_mass_star() {
00683
00684 return (!low_mass_star() && !high_mass_star())?true:false;
00685 }
00686
00687 bool single_star::high_mass_star() {
00688
00689 if(remnant())
00690 return (get_total_mass()>cnsts.parameters(medium_mass_star_mass_limit))
00691 ?true :false;
00692 else
00693 return (get_relative_mass()>cnsts.parameters(medium_mass_star_mass_limit))
00694 ?true :false;
00695 }
00696
00697 void single_star::read_element() {
00698
00699 real total_mass, log_temp, log_lum;
00700 real bol_corr, temp, mv;
00701 int type = (int)star_type;
00702 cin >> type >> relative_age >> relative_mass
00703 >> total_mass >> core_mass >> radius >> log_temp
00704 >> log_lum >> bol_corr >> mv >> velocity
00705 >> magnetic_field >> rotation_period;
00706
00707 envelope_mass = total_mass - core_mass;
00708 temp = pow(log_temp, 10);
00709 luminosity = pow(log_lum, 10);
00710 }
00711
00712 void single_star::put_element() {
00713
00714 ofstream outfile("binev.data", ios::app|ios::out);
00715 if (!outfile) cerr << "error: couldn't create file binev.data"<<endl;
00716
00717 real bol_corr = bolometric_correction();
00718 real mv = magnitude();
00719 outfile << star_type << " " << relative_age << " "
00720 << relative_mass << " " << get_total_mass() << " "
00721 << core_mass << " " << radius << " "
00722 << log10(temperature()) << " "
00723 << log10(luminosity) << " " << bol_corr << " "
00724 << mv << " " << " " << velocity << " "
00725 << magnetic_field << rotation_period << endl;
00726
00727 outfile.close();
00728 }
00729
00730 void single_star::dump(ostream & s, bool brief) {
00731
00732 if (brief) {
00733
00734 s << get_node()->format_label() << " "
00735 << get_current_time() << " "
00736 << "0 1 ";
00737 s << get_node()->format_label() << " "
00738 << get_element_type() << " "
00739 << get_total_mass() << " "
00740 << radius << " ";
00741 s << "0 0 0 0" << endl;
00742 }
00743 else
00744 {
00745 real bol_corr = bolometric_correction();
00746 int s1, s2, s3, s4, s5, s6;
00747 s1 = get_spec_type(Emission);
00748 s2 = get_spec_type(Blue_Straggler);
00749 s3 = get_spec_type(Barium);
00750 s4 = get_spec_type(Rl_filling) + get_spec_type(Accreting);
00751 s5 = get_spec_type(Runaway);
00752 s6 = get_spec_type(Merger);
00753
00754 s << "1\n ";
00755 s << get_element_type() << " " << s1 << " " << s2 << " "
00756 << s3 << " " << s4 << " " << s5 << " " << s6 << endl;
00757 s <<" " << identity
00758 << " " << current_time
00759 << " " << relative_age
00760 << " " << relative_mass
00761 << " " << get_total_mass()
00762 << " " << core_mass
00763 << " " << radius
00764 << " " << effective_radius
00765 << " " << log10(temperature())
00766 << " " << log10(luminosity)
00767 << " " << bol_corr
00768 << " " << magnitude()
00769 << " " << velocity
00770 << " " << magnetic_field
00771 << " " << rotation_period
00772 << endl;
00773 }
00774 }
00775
00776 void single_star::dump(char * filename, bool brief) {
00777
00778 ofstream s(filename, ios::app|ios::out);
00779 if (!s) cerr << "error: couldn't create file "<<filename<<endl;
00780
00781 if (brief) {
00782
00783 s << get_node()->format_label() << " "
00784 << get_current_time() << " "
00785 << "0 1 ";
00786 s << get_node()->format_label() << " "
00787 << get_element_type() << " "
00788 << get_total_mass() << " "
00789 << radius << " ";
00790 s << "0 0 0 0" << endl;
00791
00792 }
00793 else
00794 {
00795
00796 real bol_corr = bolometric_correction();
00797 int s1, s2, s3, s4, s5, s6;
00798 s1 = get_spec_type(Emission);
00799 s2 = get_spec_type(Blue_Straggler);
00800 s3 = get_spec_type(Barium);
00801 s4 = get_spec_type(Rl_filling) + get_spec_type(Accreting);
00802 s5 = get_spec_type(Runaway);
00803 s6 = get_spec_type(Merger);
00804
00805 s << "1\n ";
00806 s << get_element_type() << " " << s1 << " " << s2 << " "
00807 << s3 << " " << s4 << " " << s5 << " " << s6 << endl;
00808 s <<" " << identity
00809 << " " << current_time
00810 << " " << relative_age
00811 << " " << relative_mass
00812 << " " << get_total_mass()
00813 << " " << core_mass
00814 << " " << radius
00815 << " " << effective_radius
00816 << " " << log10(temperature())
00817 << " " << log10(luminosity)
00818 << " " << bol_corr
00819 << " " << magnitude()
00820 << " " << velocity
00821 << " " << magnetic_field
00822 << " " << rotation_period
00823 << endl;
00824
00825 }
00826 s.close();
00827 }
00828
00829 void single_star::put_state() {
00830
00831 star_state str;
00832 str.init_star_state(dynamic_cast(single_star*, this));
00833 str.make_star_state(dynamic_cast(single_star*, this));
00834
00835 str.put_star_state();
00836 }
00837
00838 void single_star::put_hrd(ostream & s) {
00839
00840 int s1, s2, s3, s4, s5, s6;
00841 s1 = get_spec_type(Emission);
00842 s2 = get_spec_type(Blue_Straggler);
00843 s3 = get_spec_type(Barium);
00844 s4 = get_spec_type(Rl_filling) + get_spec_type(Accreting);
00845 s5 = get_spec_type(Runaway);
00846 s6 = get_spec_type(Merger);
00847
00848 s << "1\n ";
00849 s << s1 << " " << s2 << " " << s3 << " " << s4 << " "
00850 << s5 << " " << s6 << " ";
00851 s << get_total_mass()
00852 << " " << log10(temperature())
00853 << " " << log10(luminosity)
00854 << endl;
00855 }
00856
00857 void single_star::refresh_memory() {
00858
00859 previous.star_type = get_element_type();
00860 previous.current_time = current_time;
00861 previous.last_update_age = last_update_age;
00862 previous.next_update_age = next_update_age;
00863 previous.relative_age = relative_age;
00864 previous.relative_mass = relative_mass;
00865 previous.envelope_mass = envelope_mass;
00866 previous.core_mass = core_mass;
00867 previous.COcore_mass = COcore_mass;
00868
00869 previous.radius = radius;
00870 previous.effective_radius = effective_radius;
00871
00872
00873 previous.magnetic_field = magnetic_field;
00874 previous.rotation_period = rotation_period;
00875 previous.birth_mass = birth_mass;
00876 }
00877
00878 void single_star::recall_memory() {
00879
00880 star_type = previous.star_type;
00881 current_time = previous.current_time;
00882 last_update_age = previous.last_update_age;
00883 next_update_age = previous.next_update_age;
00884 relative_age = previous.relative_age;
00885 relative_mass = previous.relative_mass;
00886 envelope_mass = previous.envelope_mass;
00887 core_mass = previous.core_mass;
00888 COcore_mass = previous.COcore_mass;
00889
00890 radius = previous.radius;
00891 effective_radius = previous.effective_radius;
00892
00893
00894 magnetic_field = previous.magnetic_field;
00895 rotation_period = previous.rotation_period;
00896 birth_mass = previous.birth_mass;
00897 }
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909 real single_star::mass_ratio_mdot_limit(real mdot) {
00910
00911
00912
00913 return mdot;
00914
00915 real accretor_mass = 0;
00916
00917 if (is_binary_component())
00918 get_companion()->get_total_mass();
00919
00920 if (accretor_mass<get_total_mass()) {
00921 real mdot_max = get_total_mass() - accretor_mass;
00922 if (mdot>mdot_max)
00923 mdot = mdot_max;
00924 }
00925
00926 int p = cerr.precision(HIGH_PRECISION);
00927 PRC(accretor_mass);PRL(get_total_mass());
00928 cerr.precision(p);
00929
00930 return mdot;
00931 }
00932
00933
00934
00935
00936 real single_star::accretion_limit(const real mdot, const real dt) {
00937
00938
00939
00940
00941
00942 real r_rl = get_binary()->roche_radius(this);
00943 real mdot_kh = dt*relative_mass/kelvin_helmholds_timescale();
00944 real accretion = log10(r_rl/effective_radius)
00945 / pow(10, expansionB(relative_mass));
00946
00947 accretion = max(accretion, 0.);
00948 real mdot_max = mdot_kh*pow(accretion, 1./expansionA(relative_mass));
00949 mdot_max = max(mdot_max, 0.);
00950
00951 return min(mdot, mdot_max);
00952
00953
00954
00955
00956
00957 }
00958
00959 void single_star::adjust_donor_radius(const real delta_m) {
00960
00961
00962 real zeta_th = zeta_thermal();
00963
00964
00965 real delta_r = -1 * effective_radius * zeta_th * delta_m/relative_mass;
00966
00967 effective_radius += delta_r;
00968
00969
00970
00971
00972 if (is_binary_component() &&
00973 get_binary()->get_current_mass_transfer_type()==Nuclear) {
00974 effective_radius = radius;
00975 }
00976
00977
00978 }
00979
00980
00981
00982 void single_star::adjust_accretor_radius(const real mdot, const real dt) {
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994 if (mdot>0) {
00995 real mdot_kh = relative_mass*dt/kelvin_helmholds_timescale();
00996
00997 real r_fr = expansionA(relative_mass)*log10(mdot/mdot_kh)
00998 + expansionB(relative_mass);
00999 if (r_fr>0.5)
01000 r_fr = 0.5;
01001
01002
01003
01004 real r_l = get_binary()->roche_radius(this);
01005 effective_radius = max(min(r_l, effective_radius),
01006 radius*pow(10, pow(10, r_fr)));
01007
01008 }
01009 }
01010
01011 real single_star::expansionA(const real m) {
01012
01013
01014 real rc, inc;
01015 if (m<=3) {
01016 rc = 0.120;
01017 inc = 0.359;
01018 }
01019 else if (m<=5) {
01020 rc = 0.144;
01021 inc = 0.289;
01022 }
01023 else if (m<=10) {
01024 rc = 0.123;
01025 inc = 0.393;
01026 }
01027 else {
01028 rc = 0.085;
01029 inc = 0.772;
01030 }
01031
01032 return inc + rc*m;
01033 }
01034
01035 real single_star::expansionB(const real m) {
01036
01037
01038 real rc, inc;
01039 if (m<=3) {
01040 rc = -0.273;
01041 inc = -0.828;
01042 }
01043 else if (m<=5) {
01044 rc = -0.192;
01045 inc = -1.071;
01046 }
01047 else if (m<=10) {
01048 rc = -0.106;
01049 inc = -1.50;
01050 }
01051 else {
01052 rc = -7.08e-2;
01053 inc = -1.852;
01054 }
01055
01056 real value = inc + rc*m;
01057
01058 return min(1., value);
01059 }
01060
01061
01062
01063 star* single_star::merge_elements(star* str) {
01064
01065 star* merged_star = this;
01066
01067 real m_conserved = get_total_mass() + str->get_total_mass();
01068
01069 if (str->get_element_type()!=Main_Sequence) {
01070
01071
01072
01073
01074
01075
01076 add_mass_to_core(str->get_core_mass());
01077
01078 if ((str->get_element_type()==Neutron_Star ||
01079 str->get_element_type()==Black_Hole) &&
01080 core_mass < cnsts.parameters(helium2neutron_star)) {
01081 real dm = cnsts.parameters(helium2neutron_star) - core_mass;
01082 core_mass = cnsts.parameters(helium2neutron_star);
01083 if (envelope_mass<dm)
01084 envelope_mass = 0;
01085 else
01086 envelope_mass -= dm;
01087 }
01088
01089
01090 if (str->get_envelope_mass()>0)
01091 add_mass_to_accretor(0.5*str->get_envelope_mass());
01092
01093 }
01094 else {
01095
01096 add_mass_to_accretor(str->get_total_mass());
01097 }
01098
01099 if (get_total_mass()-m_conserved > 1.e-11) {
01100 cerr.precision(HIGH_PRECISION);
01101 cerr << "ERROR: Mass is not conserved in single_star::merge elements()"
01102 << endl;
01103
01104 PRC(get_total_mass());PRC(m_conserved);
01105 PRL(get_total_mass()-m_conserved);
01106
01107 exit(-1);
01108 }
01109
01110 spec_type[Merger]=Merger;
01111 adjust_next_update_age();
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123 if (get_relative_mass() >= cnsts.parameters(massive_star_mass_limit) &&
01124 hydrogen_envelope_star())
01125 merged_star = reduce_mass(envelope_mass);
01126 else {
01127
01128 instantaneous_element();
01129
01130
01131 }
01132
01133 cerr << "Merged star: "<<endl;
01134 merged_star->dump(cerr, false);
01135
01136 return merged_star;
01137 }
01138
01139
01140
01141 real single_star::mass_transfer_timescale(mass_transfer_type &type) {
01142
01143 type = Unknown;
01144
01145 real z_l=0, mass_ratio = 1;
01146 if (is_binary_component()) {
01147 mass_ratio = get_companion()->get_total_mass()/get_total_mass();
01148 z_l = get_binary()->zeta(this, get_companion());
01149 }
01150
01151 real z_ad = zeta_adiabatic();
01152 real z_th = zeta_thermal();
01153
01154 real mtt;
01155 if (z_ad>z_l && z_th>z_l) {
01156
01157 mtt = nucleair_evolution_timescale();
01158 type = Nuclear;
01159 }
01160 else if (z_ad>z_l && z_l>z_th) {
01161 mtt = kelvin_helmholds_timescale();
01162
01163 type = Thermal;
01164 }
01165 else if (z_l>z_ad) {
01166 mtt = sqrt(kelvin_helmholds_timescale()*dynamic_timescale());
01167
01168
01169
01170
01171 type = Dynamic;
01172 }
01173 else {
01174 cerr << "No clear indication for mass transfer timescale: "
01175 << "Kelvin-Helmholds time-scale assumed."<<endl;
01176
01177 mtt = kelvin_helmholds_timescale();
01178 type = Unknown;
01179 }
01180
01181 if (low_mass_star()) {
01182
01183 real mdot = get_binary()
01184 ->mdot_according_to_roche_radius_change(this,
01185 get_companion());
01186 if (mdot>0) {
01187 real mtt_rl = get_relative_mass()/mdot;
01188 if(mtt>mtt_rl) {
01189 mtt = mtt_rl;
01190 type = AML_driven;
01191 }
01192
01193 }
01194 }
01195
01196 if (REPORT_MASS_TRANSFER_TIMESCALE) {
01197 cerr << "single_star::mass_transfer_timescale()" << endl;
01198 cerr << " star id = " << identity
01199 << " Zeta (lobe, ad, th) = ("
01200 << z_l <<", "<<z_ad<<", "<<z_th<<") : " << endl;
01201 cerr << type_string(type);
01202 cerr<<": dm/dt=" <<get_relative_mass()/(mtt*1.e+6)
01203 << " [Msun/yr]" << endl;
01204 }
01205
01206 return mtt;
01207 }
01208
01209
01210 real single_star::zeta_adiabatic() {
01211
01212
01213
01214
01215
01216
01217
01218 real r_dconv = 2.4*pow(relative_mass,1.56);
01219 if (relative_mass > 10 )
01220 r_dconv = 5.24*pow(relative_mass,1.32);
01221 else if (relative_mass > 5)
01222 r_dconv = 1.33*pow(relative_mass,1.93);
01223
01224 if (radius < r_dconv) {
01225 return 12.25;
01226
01227 }
01228 else {
01229
01230 real x = core_mass/get_total_mass();
01231 real A = -0.220823;
01232 real B = -2.84699;
01233 real C = 32.0344;
01234 real D = -75.6863;
01235 real E = 57.8109;
01236
01237
01238
01239
01240
01241 return A + x*(B + x*(C + x*(D + x*E)));
01242
01243 }
01244
01245 }
01246
01247
01248 real single_star::zeta_thermal() {
01249
01250
01251 real z;
01252 if (low_mass_star())
01253 z = 0;
01254 else
01255 z = 0;
01256
01257 return z;
01258 }
01259
01260
01261 void single_star::add_mass_to_core(const real mdot) {
01262
01263 if (mdot<=0) {
01264 cerr << "single_star::add_mass_to_core(mdot=" << mdot << ")"<<endl;
01265 cerr << "mdot (" << mdot << ") smaller than zero!" << endl;
01266
01267 }
01268 else {
01269 adjust_accretor_age(mdot, false);
01270 core_mass += mdot;
01271 accreted_mass += mdot;
01272
01273 if (relative_mass<get_total_mass())
01274 update_relative_mass(get_total_mass());
01275
01276 }
01277
01278 }
01279
01280
01281
01282
01283
01284 real single_star::add_mass_to_accretor(const real mdot) {
01285
01286
01287
01288
01289
01290 if (mdot<=0) {
01291 cerr << "single_star::add_mass_to_accretor(mdot=" << mdot << ")"<<endl;
01292 cerr << "mdot (" << mdot << ") smaller than zero!" << endl;
01293
01294 set_spec_type(Accreting, false);
01295
01296 return 0;
01297 }
01298 else {
01299 adjust_accretor_age(mdot);
01300 envelope_mass += mdot;
01301 accreted_mass += mdot;
01302
01303 if (relative_mass<get_total_mass())
01304 update_relative_mass(get_total_mass());
01305
01306 set_spec_type(Accreting);
01307
01308 }
01309
01310
01311 return mdot;
01312 }
01313
01314 real single_star::add_mass_to_accretor(real mdot, const real dt) {
01315
01316
01317
01318
01319
01320 if (mdot<0) {
01321 cerr << "single_star::add_mass_to_accretor(mdot=" << mdot
01322 << ", dt=" << dt << ")"<<endl;
01323 cerr << "mdot (" << mdot << ") smaller than zero!" << endl;
01324 return 0;
01325 }
01326
01327 mdot = accretion_limit(mdot, dt);
01328
01329 adjust_accretor_age(mdot);
01330 envelope_mass += mdot;
01331 accreted_mass += mdot;
01332
01333 if (relative_mass<get_total_mass())
01334 update_relative_mass(get_total_mass());
01335
01336 adjust_accretor_radius(mdot, dt);
01337
01338 set_spec_type(Accreting);
01339
01340 return mdot;
01341 }
01342
01343
01344
01345 void single_star::update() {
01346
01347
01348
01349
01350
01351
01352
01353 core_radius = helium_core_radius();
01354
01355
01356
01357 effective_radius = max(radius,effective_radius);
01358
01359
01360
01361
01362
01363
01364 detect_spectral_features();
01365
01366 }
01367
01368
01369 void single_star::detect_spectral_features() {
01370
01371
01372 set_spec_type(Emission, false);
01373 set_spec_type(Blue_Straggler, false);
01374 set_spec_type(Barium, false);
01375
01376
01377 if (is_binary_component())
01378 if (!remnant() &&
01379 !get_companion()->hydrogen_envelope_star() &&
01380 accreted_mass >= cnsts.parameters(Barium_star_mass_limit)
01381 * relative_mass)
01382 set_spec_type(Barium);
01383 }
01384
01385
01386
01387
01388
01389 real single_star::accrete_from_stellar_wind(const real mdot, const real dt) {
01390
01391
01392
01393 real alpha_wind = 0.5;
01394 real v_wind = get_companion()->wind_velocity();
01395
01396 real acc_radius = pow(cnsts.physics(G)*cnsts.parameters(solar_mass)
01397 * get_total_mass()
01398 / pow(v_wind*cnsts.physics(km_per_s), 2),2)
01399 / cnsts.parameters(solar_radius);
01400 real wind_acc = alpha_wind/(sqrt(1-pow(get_binary()->get_eccentricity(), 2))
01401 * pow(cnsts.parameters(solar_radius)
01402 * get_binary()->get_semi(),2));
01403 real v_factor = 1/pow(1+pow(velocity/v_wind, 2), 3./2.);
01404
01405 real mass_fraction = acc_radius*wind_acc*v_factor;
01406
01407
01408
01409
01410
01411 mass_fraction = min(0.9, mass_fraction);
01412
01413 return add_mass_to_accretor(mass_fraction*mdot, dt);
01414 }
01415
01416
01417
01418
01419 real single_star::tf2_energy_diss(const real eta) {
01420
01421 const real coeff2[] = {-0.397, 1.678, 1.277, -12.42, 9.446, -5.550};
01422
01423 real y = log10(eta);
01424 real logT = ((((coeff2[5]*y + coeff2[4])*y + coeff2[3])*y
01425 + coeff2[2])*y + coeff2[1])*y + coeff2[0];
01426
01427 return pow(10., logT);
01428 }
01429
01430
01431
01432
01433 real single_star::tf3_energy_diss(const real eta) {
01434
01435 const real coeff3[] = {-0.909, 1.574, 12.37, -57.40, 80.10, -46.43};
01436
01437 real y = log10(eta);
01438 real logT = ((((coeff3[5]*y + coeff3[4])*y + coeff3[3])*y
01439 + coeff3[2])*y + coeff3[1])*y + coeff3[0];
01440
01441 return pow(10., logT);
01442 }
01443
01444
01445 void single_star::print_status() {
01446
01447 star_state str;
01448 str.init_star_state((single_star*)this);
01449 str.make_star_state((single_star*)this);
01450
01451 cout << " [M = " << get_total_mass()
01452 << ", R = " << effective_radius
01453 << ", v = " << velocity << "] "
01454 << type_string(get_element_type()) << " ";
01455 str.put_star_state();
01456
01457 }
01458
01459
01460 void single_star::print_roche() {
01461
01462 real r = effective_radius;
01463 if (effective_radius<radius) r = 1.e6;
01464
01465 cerr << get_total_mass() << " " << r << " ";
01466
01467 }
01468
01469 void single_star::set_spec_type(star_type_spec s,
01470 bool on) {
01471
01472 if (on) spec_type[s] = s;
01473 else spec_type[s] = NAC;
01474 }
01475
01476
01477
01478 real single_star::angular_momentum() {
01479
01480 real m = get_total_mass()*cnsts.parameters(solar_mass);
01481 real r = effective_radius*cnsts.parameters(solar_radius);
01482
01483
01484 if (is_binary_component()) {
01485 r = min(r,
01486 get_binary()->roche_radius(this)*cnsts.parameters(solar_radius));
01487 }
01488
01489 real o = 0;
01490 if(rotation_period>0)
01491 o = 2*PI/rotation_period;
01492 else if (is_binary_component())
01493 o = 2*PI/(get_binary()->get_period()*cnsts.physics(days));
01494
01495 return gyration_radius_sq()*m*o*pow(r, 2);
01496
01497 }
01498
01499 real single_star::rejuvenation_fraction(const real mdot_fr) {
01500
01501 real rejuvenation = (1-pow(mdot_fr,
01502 cnsts.parameters(rejuvenation_exponent)));
01503
01504
01505 if(is_binary_component() &&
01506 !get_companion()->hydrogen_envelope_star())
01507 rejuvenation = 1;
01508
01509 return rejuvenation;
01510 }
01511
01512 void single_star::stellar_wind(const real dt) {
01513
01514
01515
01516
01517
01518
01519 real end_time = next_update_age - last_update_age;
01520
01521
01522 real relative_time = relative_age - last_update_age;
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532 if (relative_mass >= cnsts.parameters(super_giant2neutron_star) &&
01533 relative_mass < 85.) {
01534 end_time = nucleair_evolution_time();
01535
01536 relative_time = relative_age;
01537 }
01538
01539
01540
01541
01542
01543
01544
01545 real wind_mass = wind_constant
01546 * (pow(relative_time/end_time,
01547 cnsts.parameters(massive_star_mass_loss_law))
01548 - pow((relative_time-dt)/end_time,
01549 cnsts.parameters(massive_star_mass_loss_law)));
01550
01551
01552
01553
01554
01555
01556 if (wind_mass>=envelope_mass) {
01557 wind_mass = envelope_mass;
01558 radius = core_radius;
01559 }
01560
01561
01562
01563 if (is_binary_component())
01564 get_binary()->adjust_binary_after_wind_loss(this, wind_mass, dt);
01565 else {
01566
01567
01568
01569 reduce_mass(wind_mass);
01570 }
01571
01572 return;
01573 }
01574
01575 void single_star::update_relative_mass(const real new_relative_mass) {
01576
01577 relative_mass = new_relative_mass;
01578 adjust_next_update_age();
01579 update_wind_constant();
01580
01581 }
01582
01583 void single_star::lose_envelope_decent() {
01584
01585
01586
01587 if (envelope_mass>0) {
01588 if (is_binary_component()) {
01589 get_binary()->adjust_binary_after_wind_loss(
01590 this, envelope_mass, POST_AGB_TIME);
01591 }
01592 else
01593 reduce_mass(envelope_mass);
01594 }
01595
01596 if (is_binary_component()) {
01597 get_companion()->set_effective_radius(get_companion()->get_radius());
01598 get_companion()->set_spec_type(Accreting, false);
01599 }
01600 }
01601
01602
01603
01604
01605 void single_star::update_wind_constant() {
01606
01607 #if 0
01608 if (relative_mass >= cnsts.parameters(massive_star_mass_limit))
01609 wind_constant = (get_relative_mass()-core_mass)
01610 * cnsts.parameters(massive_star_envelope_fraction_lost);
01611 else
01612 wind_constant = get_relative_mass()
01613 * cnsts.parameters(non_massive_star_envelope_fraction_lost);
01614
01615 #endif
01616
01617
01618
01619
01620 if (relative_mass >= cnsts.parameters(super_giant2neutron_star)) {
01621
01622 real meader_fit_dm = 0.01*pow(relative_mass,2.);
01623
01624 if (relative_mass < 85)
01625 wind_constant = meader_fit_dm;
01626 else {
01627 real final_mass = 43;
01628 wind_constant = relative_mass - final_mass;
01629 }
01630
01631 }
01632 else {
01633 wind_constant = 0;
01634 }
01635
01636 wind_constant = max(wind_constant, 0.0);
01637
01638
01639 }
01640
01641
01642 real single_star::potential_energy() {
01643
01644 real GM2_R = cnsts.physics(G)*pow(cnsts.parameters(solar_mass), 2)
01645 / cnsts.parameters(solar_radius);
01646 real p = GM2_R*get_total_mass()*get_total_mass()
01647 / get_effective_radius();
01648
01649 return -p;
01650 }
01651
01652 real single_star::kinetic_energy() {
01653
01654 real Mkm_s2 = cnsts.parameters(solar_mass)
01655 * pow(cnsts.physics(km_per_s), 2);
01656 real k = 0.5*Mkm_s2*get_total_mass()*pow(velocity, 2);
01657
01658 return k;
01659 }
01660
01661 real single_star::total_energy() {
01662 return kinetic_energy() + potential_energy();
01663 }
01664
01665 real single_star::get_evolve_timestep() {
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676 return max(next_update_age - relative_age, 0.0001);
01677
01678 }
01679
01680
01681 real single_star::final_core_mass() {
01682
01683 if (maximum_luminosity() < 15725) {
01684 return sqrt(maximum_luminosity()/47488. + 0.18) + 0.015;
01685 }
01686 else {
01687
01688
01689
01690 return 0.46 + maximum_luminosity()/(46818*pow(relative_mass,0.25));
01691 }
01692
01693 }