00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "main_sequence.h"
00011 #include "brown_dwarf.h"
00012 #include "proto_star.h"
00013
00014
00015
00016 #if 0
00017 void main_sequence::adjust_initial_star() {
00018
00019 if(relative_age<=0)
00020 relative_age = max(current_time, 0.0);
00021
00022 core_mass = main_sequence_core_mass();
00023 core_radius = main_sequence_core_radius();
00024 update_wind_constant();
00025
00026 instantaneous_element();
00027
00028 update();
00029
00030 }
00031 #endif
00032
00033 main_sequence::main_sequence(proto_star & p) : single_star(p) {
00034
00035 delete &p;
00036
00037 last_update_age = 0;
00038 relative_age = 0;
00039 relative_mass = envelope_mass + core_mass;
00040 envelope_mass = relative_mass - 0.01;
00041 core_mass = 0.01;
00042
00043 adjust_next_update_age();
00044 update_wind_constant();
00045
00046 instantaneous_element();
00047 update();
00048
00049 post_constructor();
00050 }
00051
00052 void main_sequence::update() {
00053
00054
00055
00056
00057
00058 detect_spectral_features();
00059
00060 }
00061
00062
00063
00064
00065 void main_sequence::update_wind_constant() {
00066
00067 #if 0
00068 if (relative_mass >= cnsts.parameters(massive_star_mass_limit)) {
00069
00070 real m_core = 0.073 * (1 + cnsts.parameters(core_overshoot))
00071 * pow(relative_mass, 1.42);
00072 m_core = min(m_core, cnsts.parameters(massive_star_mass_limit));
00073
00074
00075
00076 if (m_core>=35) {
00077 if (m_core<=55)
00078 m_core = 35 - 1.25 * (m_core -35);
00079 else
00080 m_core = 10 + 0.75 * (m_core-55);
00081 }
00082
00083 if (m_core>get_total_mass())
00084 m_core = get_total_mass();
00085
00086 wind_constant = (get_relative_mass()-m_core)
00087 * cnsts.parameters(massive_star_envelope_fraction_lost);
00088
00089 cerr << "Main_sequence wind treatment for stars with M >= "
00090 << cnsts.parameters(massive_star_mass_limit)
00091 << " for " << identity << endl
00092 << " M = " << get_total_mass() << " [Msun] "
00093 << " Mdot = " << wind_constant
00094 << " t^" << cnsts.parameters(massive_star_mass_loss_law)
00095 << " [Msun/Myr] "
00096 << endl;
00097 }
00098 else {
00099
00100 wind_constant = relative_mass
00101 * cnsts.parameters(non_massive_star_envelope_fraction_lost);
00102 }
00103 #endif
00104
00105
00106
00107 if (relative_mass >= cnsts.parameters(super_giant2neutron_star)) {
00108
00109 real meader_fit_dm = 0.01*pow(relative_mass,2.);
00110
00111 if (relative_mass < 85)
00112 wind_constant = meader_fit_dm;
00113 else {
00114 real final_mass = 43 + (relative_mass-85);
00115 wind_constant = relative_mass - final_mass;
00116 }
00117
00118 }
00119 else {
00120 wind_constant = 0;
00121 }
00122
00123 wind_constant = max(wind_constant, 0.0);
00124
00125 }
00126
00127
00128 void main_sequence::instantaneous_element() {
00129
00130 real alpha, beta, gamma, delta, kappa, lambda;
00131
00132 real log_mass = log10(relative_mass);
00133
00134 if (relative_mass > 1.334) {
00135
00136 alpha = 0.1509 + 0.1709*log_mass;
00137 beta = 0.06656 - 0.4805*log_mass;
00138 gamma = 0.007395 + 0.5083*log_mass;
00139 delta = (0.7388*pow(relative_mass, 1.679)
00140 - 1.968*pow(relative_mass, 2.887))
00141 / (1.0 - 1.821*pow(relative_mass, 2.337));
00142
00143 } else {
00144
00145 alpha = 0.08353 + 0.0565*log_mass;
00146 beta = 0.01291 + 0.2226*log_mass;
00147 gamma = 0.1151 + 0.06267*log_mass;
00148 delta = pow(relative_mass, 1.25)
00149 * (0.1148 + 0.8604*relative_mass*relative_mass)
00150 / (0.04651 + relative_mass*relative_mass);
00151 }
00152
00153 if (relative_mass < 1.334) {
00154 kappa = 0.2594 + 0.1348*log_mass;
00155 lambda = 0.144 - 0.8333*log_mass;
00156 } else {
00157 kappa = 0.092088 + 0.059338*log_mass;
00158 lambda = -0.05713 + log_mass*(0.3756 -0.1744*log_mass);
00159 }
00160
00161 real ff = relative_age/main_sequence_time();
00162 luminosity = base_main_sequence_luminosity()
00163 * pow(10., (ff*(ff*lambda + kappa)));
00164
00165 radius = delta*pow(10., (ff*(ff*(ff*gamma + beta) + alpha)));
00166 effective_radius = max(effective_radius, radius);
00167
00168 }
00169
00170
00171
00172 void main_sequence::evolve_element(const real end_time) {
00173
00174
00175
00176
00177 real alpha, beta, gamma, delta, kappa, lambda;
00178
00179 real dt = end_time - current_time;
00180 current_time = end_time;
00181 relative_age += dt;
00182
00183 real log_mass = log10(relative_mass);
00184
00185 if (relative_mass > 1.334) {
00186
00187 alpha = 0.1509 + 0.1709*log_mass;
00188 beta = 0.06656 - 0.4805*log_mass;
00189 gamma = 0.007395 + 0.5083*log_mass;
00190 delta = (0.7388*pow(relative_mass, 1.679)
00191 - 1.968*pow(relative_mass, 2.887))
00192 / (1.0 - 1.821*pow(relative_mass, 2.337));
00193
00194 } else if (relative_mass >= cnsts.parameters(minimum_main_sequence)) {
00195
00196 alpha = 0.08353 + 0.0565*log_mass;
00197 beta = 0.01291 + 0.2226*log_mass;
00198 gamma = 0.1151 + 0.06267*log_mass;
00199 delta = pow(relative_mass, 1.25)
00200 * (0.1148 + 0.8604*relative_mass*relative_mass)
00201 / (0.04651 + relative_mass*relative_mass);
00202
00203 } else {
00204
00205
00206
00207 star_transformation_story(Brown_Dwarf);
00208 new brown_dwarf(*this);
00209 return;
00210 }
00211
00212 if (relative_mass < 1.334) {
00213 kappa = 0.2594 + 0.1348*log_mass;
00214 lambda = 0.144 - 0.8333*log_mass;
00215 } else {
00216 kappa = 0.092088 + 0.059338*log_mass;
00217 lambda = -0.05713 + log_mass*(0.3756 -0.1744*log_mass);
00218 }
00219
00220 if (relative_age <= next_update_age) {
00221
00222 real ff = relative_age/main_sequence_time();
00223 luminosity = base_main_sequence_luminosity()
00224 * pow(10., (ff*(ff*lambda + kappa)));
00225 radius = delta*pow(10., (ff*(ff*(ff*gamma + beta) + alpha)));
00226
00227 effective_radius = max(effective_radius, radius);
00228
00229 } else {
00230
00231
00232
00233
00234 if (relative_mass < cnsts.parameters(massive_star_mass_limit)) {
00235 star_transformation_story(Hertzsprung_Gap);
00236 new hertzsprung_gap(*this);
00237 return;
00238 } else {
00239 star_transformation_story(Hyper_Giant);
00240 new hyper_giant(*this);
00241 return;
00242 }
00243 }
00244
00245 update();
00246 stellar_wind(dt);
00247 }
00248
00249 real main_sequence::bolometric_correction()
00250 {
00251
00252
00253
00254 real temp_in_kK = 0.001 * temperature();
00255
00256 real bc;
00257 if (temp_in_kK < 4.452)
00258 bc = 2.5*log10((6.859e-6*pow(temp_in_kK,8) + 9.316e-3)
00259 / (1. + 5.975e-10*pow(temp_in_kK,14)));
00260 else if (temp_in_kK < 10.84)
00261 bc = 2.5*log10((3.407e-2*pow(temp_in_kK,2.))
00262 / (1. + 1.043e-4*pow(temp_in_kK, 4.5)));
00263 else
00264 bc = 2.5*log10((2728./pow(temp_in_kK, 3.5)
00265 + 1.878e-2*temp_in_kK)
00266 / (1. + 5.362e-5*pow(temp_in_kK,3.5)));
00267
00268 return bc;
00269 }
00270
00271
00272
00273 real main_sequence::main_sequence_core_mass()
00274 {
00275 real m_core = 0.01;
00276 m_core = max(core_mass, m_core);
00277 if (m_core > get_total_mass()) m_core = get_total_mass();
00278
00279 return m_core;
00280 }
00281
00282 real main_sequence::main_sequence_core_radius()
00283 {
00284 return min(0.01, radius);
00285 }
00286
00287 #if 0
00288
00289
00290
00291 real main_sequence::add_mass_to_accretor(const real mdot) {
00292
00293 if (mdot<=0) {
00294 cerr << "main_sequence::add_mass_to_accretor(mdot=" << mdot << ")"<<endl;
00295 cerr << "mdot (" << mdot << ") smaller than zero!" << endl;
00296 cerr << "Action: No action!" << endl;
00297
00298 return 0;
00299 }
00300
00301 adjust_accretor_age(mdot);
00302 envelope_mass += mdot;
00303 accreted_mass += mdot;
00304 if (relative_mass<get_total_mass())
00305 relative_mass = get_total_mass();
00306
00307 update_wind_constant();
00308
00309 set_spec_type(Accreting);
00310
00311 return mdot;
00312 }
00313
00314
00315
00316
00317 real main_sequence::add_mass_to_accretor(real mdot, const real dt) {
00318
00319
00320
00321 if (mdot<0) {
00322 cerr << "single_star::add_mass_to_accretor(mdot=" << mdot
00323 << ", dt=" << dt << ")"<<endl;
00324 cerr << "mdot (" << mdot << ") smaller than zero!" << endl;
00325 cerr << "Action: put mdot to zero!" << endl;
00326 return 0;
00327 }
00328
00329 mdot = accretion_limit(mdot, dt);
00330 adjust_accretor_age(mdot);
00331 if (relative_mass<get_total_mass() + mdot)
00332 relative_mass = get_total_mass() + mdot;
00333
00334 update_wind_constant();
00335
00336 envelope_mass += mdot;
00337 accreted_mass += mdot;
00338
00339 adjust_accretor_radius(mdot, dt);
00340
00341 set_spec_type(Accreting);
00342
00343
00344
00345
00346
00347
00348 return mdot;
00349 }
00350 #endif
00351
00352
00353 star* main_sequence::subtrac_mass_from_donor(const real dt, real& mdot)
00354 {
00355
00356
00357 mdot = relative_mass*dt/get_binary()->get_donor_timescale();
00358
00359 mdot = mass_ratio_mdot_limit(mdot);
00360
00361 if (envelope_mass <= mdot) {
00362 mdot = envelope_mass;
00363 envelope_mass = 0;
00364 star_transformation_story(Helium_Star);
00365 return dynamic_cast(star*, new helium_star(*this));
00366 }
00367
00368 if (low_mass_star()) {
00369
00370
00371 adjust_donor_age(mdot);
00372 update_relative_mass(relative_mass-mdot);
00373 }
00374
00375 adjust_donor_radius(mdot);
00376
00377 envelope_mass -= mdot;
00378 return this;
00379
00380 }
00381
00382 star* main_sequence::merge_elements(star* str) {
00383
00384 star* merged_star = this;
00385
00386 add_mass_to_core(str->get_core_mass());
00387
00388
00389
00390
00391
00392 if (str->get_envelope_mass()>0)
00393 add_mass_to_accretor(str->get_envelope_mass());
00394
00395 spec_type[Merger]=Merger;
00396
00397 switch(str->get_element_type()) {
00398 case Hyper_Giant:
00399 case Hertzsprung_Gap:
00400 case Sub_Giant:
00401 case Horizontal_Branch:
00402 case Super_Giant:
00403 case Carbon_Star:
00404 case Helium_Star:
00405 case Helium_Giant:
00406 case Carbon_Dwarf:
00407 case Oxygen_Dwarf:
00408 case Helium_Dwarf:
00409 if (relative_mass <
00410 cnsts.parameters(massive_star_mass_limit)) {
00411 star_transformation_story(Hertzsprung_Gap);
00412
00413
00414
00415
00416
00417
00418
00419
00420 cerr << "Merge MS+wd"<<endl;
00421 PRC(relative_age);PRC(next_update_age);
00422
00423
00424 return dynamic_cast(star*, new hertzsprung_gap(*this));
00425 }
00426 else {
00427 star_transformation_story(Hyper_Giant);
00428
00429
00430 return dynamic_cast(star*, new hyper_giant(*this));
00431 }
00432 case Thorn_Zytkow :
00433 case Xray_Pulsar:
00434 case Radio_Pulsar:
00435 case Neutron_Star :
00436 case Black_Hole :
00437 star_transformation_story(Thorn_Zytkow);
00438
00439
00440 return dynamic_cast(star*, new thorne_zytkow(*this));
00441 default: instantaneous_element();
00442 }
00443
00444 return merged_star;
00445
00446 }
00447
00448
00449 void main_sequence::adjust_accretor_age(const real mdot,
00450 const bool rejuvenate=true) {
00451
00452
00453
00454 real m_rel_new;
00455 real m_tot_new = get_total_mass() + mdot;
00456 if (m_tot_new>relative_mass)
00457 m_rel_new = m_tot_new;
00458 else m_rel_new = relative_mass;
00459
00460 real t_ms_old = main_sequence_time();
00461 real t_ms_new = main_sequence_time(m_rel_new);
00462
00463 relative_age *= (t_ms_new/t_ms_old);
00464 if (rejuvenate)
00465 relative_age *= rejuvenation_fraction(mdot/m_tot_new);
00466
00467
00468
00469
00470
00471
00472 }
00473
00474
00475
00476
00477 void main_sequence::adjust_donor_age(const real mdot) {
00478
00479 real m_rel_new = get_relative_mass() - mdot;
00480
00481 relative_age *= main_sequence_time(m_rel_new)
00482 / main_sequence_time();
00483
00484 }
00485
00486
00487
00488
00489
00490 real main_sequence::zeta_adiabatic() {
00491
00492 real z;
00493
00494 if (get_relative_mass()<=0.4)
00495 z = -cnsts.mathematics(one_third);
00496 else if(low_mass_star()) {
00497 z = 2;
00498
00499 }
00500 else if(medium_mass_star()) {
00501 z = 4;
00502 }
00503 else
00504 z = 4;
00505
00506 return z;
00507 }
00508
00509
00510
00511
00512 real main_sequence::zeta_thermal() {
00513
00514 real z = -1;
00515
00516 if (get_relative_mass()<=0.4)
00517 z = 0;
00518 else if (low_mass_star())
00519 z = 0.9;
00520
00521 else
00522 z = 0.55;
00523
00524 return z;
00525 }
00526
00527 star* main_sequence::reduce_mass(const real mdot) {
00528
00529 if (envelope_mass<=mdot) {
00530 envelope_mass = 0;
00531 star_transformation_story(Helium_Star);
00532 return dynamic_cast(star*, new helium_star(*this));
00533 }
00534
00535 envelope_mass -= mdot;
00536 return this;
00537 }
00538
00539 void main_sequence::adjust_next_update_age() {
00540
00541
00542 last_update_age = 0;
00543 next_update_age = main_sequence_time();
00544 }
00545
00546 void main_sequence::detect_spectral_features() {
00547
00548 single_star::detect_spectral_features();
00549
00550 if (accreted_mass>=cnsts.parameters(B_emission_star_mass_limit))
00551 spec_type[Emission]=Emission;
00552 if (get_relative_mass() > turn_off_mass(current_time)
00553 * (1+cnsts.parameters(Blue_straggler_mass_limit)))
00554 spec_type[Blue_Straggler]=Blue_Straggler;
00555 }
00556
00557 #if 0
00558 real main_sequence::stellar_radius(const real mass, const real age) {
00559
00560 real alpha, beta, gamma, delta, kappa, lambda;
00561
00562 real log_mass = log10(mass);
00563
00564 if (mass>1.334) {
00565 alpha = 0.1509 + 0.1709*log_mass;
00566 beta = 0.06656 - 0.4805*log_mass;
00567 gamma = 0.007395 + 0.5083*log_mass;
00568 delta = (0.7388*pow(mass, 1.679)
00569 - 1.968*pow(mass, 2.887))
00570 / (1.0 - 1.821*pow(mass, 2.337));
00571 }
00572 else {
00573 alpha = 0.08353 + 0.0565*log_mass;
00574 beta = 0.01291 + 0.2226*log_mass;
00575 gamma = 0.1151 + 0.06267*log_mass;
00576 delta = pow(mass, 1.25)
00577 * (0.1148 + 0.8604*mass*mass)
00578 / (0.04651 + mass*mass);
00579 }
00580
00581 if (mass<1.334) {
00582 kappa = 0.2594 + 0.1348*log_mass;
00583 lambda = 0.144 - 0.8333*log_mass;
00584 }
00585 else {
00586 kappa = 0.092088 + 0.059338*log_mass;
00587 lambda = -0.05713 + log_mass*(0.3756 -0.1744);
00588 }
00589
00590 real t_ms = main_sequence_time(mass);
00591 real ff = age/t_ms;
00592 real r_ms = delta*pow(10., (ff*(ff*(ff*gamma + beta) + alpha)));
00593
00594 return r_ms;
00595 }
00596 #endif
00597
00598
00599 real main_sequence::gyration_radius_sq() {
00600
00601 real m = get_total_mass();
00602
00603
00604 real g = cnsts.physics(G)
00605 * m*cnsts.parameters(solar_mass)
00606 / pow(get_effective_radius() * cnsts.parameters(solar_radius), 2);
00607
00608
00609 real A = -1.5;
00610 real B = 0.2;
00611
00612
00613 if (low_mass_star()) {
00614 A = -3.8 + 1.8*m;
00615 B = 0.77 - 0.44*m;
00616 }
00617
00618 real k = pow(10., (A + B*log10(g)));
00619
00620 return k*k;
00621
00622 }
00623
00624 real main_sequence::nucleair_evolution_timescale() {
00625
00626
00627
00628 real fused_mass = 0.1*relative_mass;
00629
00630 return cnsts.parameters(energy_to_mass_in_internal_units)
00631 * fused_mass/luminosity;
00632 }
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644