00001
00002
00003
00004
00005 #include "white_dwarf.h"
00006 #include "hertzsprung_gap.h"
00007 #include "sub_giant.h"
00008 #include "super_giant.h"
00009 #include "helium_star.h"
00010 #include "helium_giant.h"
00011
00012 white_dwarf::white_dwarf(super_giant & g) : single_star(g) {
00013
00014 delete &g;
00015
00016 real m_tot = get_total_mass();
00017 core_mass = min(0.99*cnsts.parameters(kanonical_neutron_star_mass),
00018 core_mass);
00019 envelope_mass = m_tot - core_mass;
00020 accreted_mass = 0;
00021
00022 lose_envelope_decent();
00023
00024
00025 last_update_age = next_update_age;
00026
00027 relative_age = 1 + nucleair_evolution_time();
00028
00029 instantaneous_element();
00030 update();
00031
00032 post_constructor();
00033 }
00034
00035 white_dwarf::white_dwarf(sub_giant & s) : single_star(s) {
00036
00037 delete &s;
00038
00039 real m_tot = get_total_mass();
00040 core_mass = min(0.99*cnsts.parameters(Chandrasekar_mass),
00041 core_mass);
00042 envelope_mass = m_tot - core_mass;
00043 accreted_mass = 0;
00044
00045
00046 last_update_age = next_update_age;
00047
00048 lose_envelope_decent();
00049
00050 relative_age = 1 + nucleair_evolution_time();
00051
00052 instantaneous_element();
00053 update();
00054
00055 post_constructor();
00056
00057 }
00058
00059 white_dwarf::white_dwarf(hertzsprung_gap & s) : single_star(s) {
00060
00061 delete &s;
00062
00063 real m_tot = get_total_mass();
00064 core_mass = min(0.99*cnsts.parameters(Chandrasekar_mass),
00065 core_mass);
00066 envelope_mass = m_tot - core_mass;
00067 accreted_mass = 0;
00068
00069
00070 last_update_age = next_update_age;
00071
00072 lose_envelope_decent();
00073
00074 relative_age = 1 + nucleair_evolution_time();
00075
00076 instantaneous_element();
00077 update();
00078
00079 post_constructor();
00080
00081 }
00082
00083
00084 white_dwarf::white_dwarf(helium_star & h) : single_star(h) {
00085
00086 delete &h;
00087
00088 real m_tot = get_total_mass();
00089 core_mass = min(0.99*cnsts.parameters(Chandrasekar_mass),
00090 core_mass);
00091 envelope_mass = m_tot - core_mass;
00092 accreted_mass = 0;
00093
00094
00095 last_update_age = next_update_age;
00096
00097 lose_envelope_decent();
00098
00099 relative_age = 1 + nucleair_evolution_time();
00100
00101 instantaneous_element();
00102 update();
00103
00104 post_constructor();
00105
00106 }
00107
00108
00109 white_dwarf::white_dwarf(helium_giant & h) : single_star(h) {
00110
00111 delete &h;
00112
00113 real m_tot = get_total_mass();
00114 core_mass = min(0.99*cnsts.parameters(Chandrasekar_mass),
00115 core_mass);
00116 envelope_mass = m_tot - core_mass;
00117 accreted_mass = 0;
00118
00119
00120 last_update_age = next_update_age;
00121
00122 lose_envelope_decent();
00123
00124 relative_age = 1 + nucleair_evolution_time();
00125
00126 instantaneous_element();
00127 update();
00128
00129 post_constructor();
00130
00131 }
00132
00133 #if 0
00134 void white_dwarf::adjust_initial_star() {
00135
00136 if (core_mass<=0) {
00137 core_mass = get_total_mass();
00138 envelope_mass = 0;
00139 if (core_mass>=cnsts.parameters(Chandrasekar_mass)) {
00140 envelope_mass = core_mass-0.75;
00141 core_mass = 0.75;
00142 }
00143 }
00144
00145 if(relative_age<=0)
00146 relative_age = max(current_time, nucleair_evolution_time());
00147
00148 if (relative_mass>cnsts.parameters(super_giant2neutron_star)) {
00149 cerr<<"White_dwarf with high mass!"
00150 <<"\n should be turned into a neutron star"
00151 <<"\nadopt maximum WD relative mass"<<endl;
00152 relative_mass = cnsts.parameters(super_giant2neutron_star);
00153 return;
00154 }
00155 }
00156 #endif
00157
00158 void white_dwarf::instantaneous_element() {
00159
00160
00161 next_update_age = relative_age + cnsts.safety(maximum_timestep);
00162
00163 luminosity = 40;
00164
00165
00166
00167
00168
00169 real mu = 2.;
00170
00171 effective_radius =
00172 core_radius =
00173 radius = white_dwarf_radius(core_mass, relative_age);
00174
00175
00176
00177 }
00178
00179
00180 void white_dwarf::evolve_element(const real end_time) {
00181
00182 real dt = end_time - current_time;
00183 current_time = end_time;
00184 relative_age += dt;
00185
00186
00187
00188
00189 if (core_mass > cnsts.parameters(Chandrasekar_mass) ||
00190 core_mass <= cnsts.safety(minimum_mass_step)) {
00191
00192
00193
00194
00195 if (is_binary_component())
00196 get_binary()->dump("binev.data", false);
00197 else
00198 dump("binev.data", false);
00199
00200 star_transformation_story(Disintegrated);
00201 new disintegrated(*this);
00202
00203 return;
00204 }
00205
00206 real t_nuc = nucleair_evolution_time();
00207 next_update_age = relative_age + cnsts.safety(maximum_timestep);
00208
00209
00210 if (t_nuc>=relative_age) {
00211 luminosity = 40;
00212 relative_age = t_nuc;
00213 }
00214 else {
00215
00216 real fit_mass = min(0.6, max(0.18, get_total_mass()));
00217 real l_max = pow(10, (3.83 - 4.77* fit_mass));
00218 luminosity = l_max/pow((relative_age - t_nuc), 1.4);
00219 }
00220
00221
00222
00223
00224
00225
00226 real mu = 2.;
00227 core_radius =
00228 radius = white_dwarf_radius(core_mass, relative_age);
00229
00230
00231
00232
00233
00234
00235 real m_crit = 1.7e-4*pow(get_total_mass(),-0.7)
00236 * pow(69.9*radius,2.8);
00237
00238 if (envelope_mass >= m_crit)
00239 thermo_nucleair_flash(dt);
00240
00241
00242
00243
00244
00245
00246 update();
00247 }
00248
00249 void white_dwarf::update() {
00250
00251 detect_spectral_features();
00252
00253
00254 effective_radius = max(effective_radius, radius);
00255
00256 }
00257
00258
00259
00260 real white_dwarf::white_dwarf_radius(real mass, real time) {
00261
00262 real r;
00263 if (mass < 0.8) {
00264 real a,b;
00265 if (mass < 0.4) {
00266 if (mass < 0.2) mass = 0.2;
00267
00268 a = lineair_interpolation(mass , 0.2, 0.4, 0.1, 0.03);
00269 b = lineair_interpolation(mass , 0.2, 0.4, 0.0175, 0.0044);
00270 }
00271 else if (mass < 0.6) {
00272
00273 a = lineair_interpolation(mass, 0.4, 0.6, 0.03, 0.017);
00274 b = lineair_interpolation(mass, 0.4, 0.6, 0.0044, 0.001);
00275 }
00276 else {
00277
00278 a = lineair_interpolation(mass, 0.6, 0.8, 0.017, 0.011);
00279 b = lineair_interpolation(mass, 0.6, 0.8, 0.001, 0.0005);
00280 }
00281 r = a - b*log10(time);
00282 }
00283 else {
00284
00285
00286 real mu = 2.;
00287 real m_rel = min(0.99, mass / cnsts.parameters(Chandrasekar_mass));
00288 r = (0.0225/mu)
00289 * sqrt(1./pow(m_rel, cnsts.mathematics(two_third))
00290 - pow(m_rel, cnsts.mathematics(two_third)));
00291 }
00292
00293 return min(0.1, r);
00294 }
00295
00296 void white_dwarf::accrete_from_envelope(const real dt) {
00297
00298 if (envelope_mass>0) {
00299 real mdot = cnsts.parameters(white_dwarf_accretion_limit)
00300 * accretion_limit(envelope_mass, dt);
00301
00302 core_mass += mdot;
00303 envelope_mass -= mdot;
00304 }
00305 }
00306
00307
00308 void white_dwarf::thermo_nucleair_flash(const real dt) {
00309
00310 cerr<<"void white_dwarf::thermo_nucleair_flash() mass="
00311 << envelope_mass<<" "<<get_core_mass()<<endl;
00312 cerr<<" "<<get_total_mass()<<endl;
00313
00314 real mdot = accretion_limit(envelope_mass, dt);
00315 if (is_binary_component() &&
00316 get_binary()->get_bin_type()!=Merged &&
00317 get_binary()->get_bin_type()!=Disrupted) {
00318
00319
00320 cerr << "Perform binary action"<<endl;
00321 cerr << " "<<get_total_mass()<<" a = "
00322 <<get_binary()->get_semi();
00323
00324 if (get_binary()->roche_radius(this)<=1.0)
00325 common_envelope(mdot);
00326 else
00327 nova(mdot);
00328
00329 cerr<<" -->"<< get_total_mass()<<" a = "
00330 << get_binary()->get_semi()<<endl;
00331 }
00332
00333 envelope_mass -= mdot;
00334
00335 }
00336
00337 void white_dwarf::nova(const real mdot) {
00338
00339 real ecc = mdot/(get_binary()->get_total_mass()-mdot);
00340
00341 get_binary()->set_semi((1+ecc)*get_binary()->get_semi());
00342 }
00343
00344 void white_dwarf::common_envelope(const real mdot) {
00345
00346 if (is_binary_component() &&
00347 get_binary()->get_semi()>radius) {
00348
00349 real semi = get_binary()->get_semi();
00350 real m_comp = get_companion()->get_total_mass();
00351 real r_lobe = get_binary()->roche_radius(this)/semi;
00352 real a_spi = semi*((get_total_mass()-mdot)/get_total_mass())
00353 / (1. + (2.*mdot
00354 / (cnsts.parameters(common_envelope_efficiency)
00355 * cnsts.parameters(envelope_binding_energy)
00356 * r_lobe*m_comp)));
00357
00358 if (a_spi>=radius)
00359 get_binary()->set_semi(a_spi);
00360 else
00361 get_binary()->set_semi(radius);
00362 }
00363 }
00364
00365 star* white_dwarf::subtrac_mass_from_donor(const real dt, real& mdot) {
00366
00367 mdot = relative_mass*dt/get_binary()->get_donor_timescale();
00368 mdot = mass_ratio_mdot_limit(mdot);
00369
00370 if (mdot<=envelope_mass)
00371 envelope_mass -= mdot;
00372 else {
00373 mdot -= envelope_mass;
00374 envelope_mass = 0;
00375 if (mdot >= core_mass)
00376 mdot = core_mass - cnsts.safety(minimum_mass_step);
00377 core_mass -= mdot;
00378 }
00379
00380 return this;
00381 }
00382
00383 real white_dwarf::add_mass_to_accretor(const real mdot) {
00384
00385 if (mdot<0) {
00386 cerr << "white_dwarf::add_mass_to_accretor(mdot="
00387 << mdot << ")"<<endl;
00388 cerr << "mdot (" << mdot << ") smaller than zero!" << endl;
00389
00390 return 0;
00391 }
00392
00393 adjust_accretor_age(mdot);
00394 envelope_mass += mdot;
00395 relative_mass = max(relative_mass, get_total_mass());
00396
00397 set_spec_type(Accreting);
00398
00399 return mdot;
00400
00401 }
00402
00403 real white_dwarf::add_mass_to_accretor(real mdot, const real dt) {
00404
00405 if (mdot<0) {
00406 cerr << "white_dwarf::add_mass_to_accretor(mdot="
00407 << mdot << ")"<<endl;
00408 cerr << "mdot (" << mdot << ") smaller than zero!" << endl;
00409
00410 mdot = 0;
00411 }
00412
00413
00414
00415
00416 real mu =1;
00417 if (is_binary_component() &&
00418 !get_companion()->hydrogen_envelope_star()) mu =2;
00419
00420
00421 if (mdot >= eddington_limit(radius, dt, mu)) {
00422 effective_radius = min(10., get_binary()->roche_radius(this));
00423 }
00424
00425
00426 mdot = accretion_limit(mdot, dt);
00427
00428
00429
00430
00431
00432
00433
00434 if (is_binary_component() &&
00435 get_companion()->hydrogen_envelope_star()
00436 && mdot < minimum_steady_burning(dt)) {
00437
00438 envelope_mass += mdot;
00439 }
00440 else {
00441
00442 core_mass += mdot;
00443 accreted_mass += mdot;
00444 }
00445
00446 adjust_accretor_age(mdot);
00447 envelope_mass += mdot;
00448 relative_mass = max(relative_mass, get_total_mass());
00449
00450 set_spec_type(Accreting);
00451
00452 return mdot;
00453
00454 }
00455
00456 #if 0
00457 real white_dwarf::accretion_limit(const real mdot, const real dt) {
00458
00459 real eddington = 1.5e-08*cnsts.parameters(solar_radius)*radius*dt;
00460
00461 if(mdot>=eddington) return eddington;
00462
00463 return mdot;
00464 }
00465 #endif
00466
00467 real white_dwarf::accretion_limit(const real mdot, const real dt) {
00468
00469 return min(maximum_steady_burning(dt), mdot);
00470
00471 }
00472
00473
00474
00475 real white_dwarf::maximum_steady_burning(const real dt) {
00476
00477
00478 real steady_burning = 4.e-1*pow(get_total_mass(),1.8)*dt;
00479 return steady_burning;
00480 }
00481
00482 real white_dwarf::minimum_steady_burning(const real dt) {
00483
00484
00485 return 1.8e-7*pow(get_total_mass(),2.7)*dt;
00486
00487 }
00488
00489
00490 void white_dwarf::adjust_accretor_age(const real mdot,
00491 const bool rejuvenate) {
00492
00493 real m_rel_new;
00494 real m_tot_new = get_total_mass() + mdot;
00495 if (m_tot_new>relative_mass)
00496 m_rel_new = m_tot_new;
00497 else m_rel_new = relative_mass;
00498
00499 real t_nuc_old = nucleair_evolution_time();
00500 real t_nuc_new = nucleair_evolution_time(m_rel_new);
00501
00502 real dtime = relative_age - t_nuc_old;
00503
00504 relative_age = t_nuc_new + dtime
00505 * (1-pow(mdot/(get_total_mass()+mdot),
00506 cnsts.parameters(rejuvenation_exponent)));
00507
00508 }
00509
00510 real white_dwarf::zeta_thermal() {
00511
00512
00513
00514
00515 return -cnsts.mathematics(one_third);
00516 }
00517
00518 star* white_dwarf::merge_elements(star* str) {
00519
00520 envelope_mass = 0;
00521
00522 real merger_core = str->get_core_mass();
00523
00524 add_mass_to_accretor(str->get_envelope_mass());
00525
00526 if (relative_mass<get_total_mass() + merger_core)
00527 relative_mass=get_total_mass() + merger_core;
00528 core_mass += merger_core;
00529
00530 spec_type[Merger]=Merger;
00531 instantaneous_element();
00532
00533 return this;
00534 }
00535
00536 star* white_dwarf::reduce_mass(const real mdot) {
00537
00538 if (envelope_mass<+mdot) {
00539 real mdot_rest = mdot - envelope_mass;
00540 envelope_mass = 0;
00541 if (mdot_rest >= core_mass)
00542 mdot_rest = core_mass - cnsts.safety(minimum_mass_step);
00543 core_mass -= mdot_rest;
00544 }
00545 else envelope_mass -= mdot;
00546
00547 return this;
00548 }
00549
00550
00551 real white_dwarf::gyration_radius_sq() {
00552
00553 return cnsts.parameters(homogeneous_sphere_gyration_radius_sq);
00554 }
00555
00556 stellar_type white_dwarf::get_element_type(){
00557
00558 if (core_mass < cnsts.parameters(helium_dwarf_mass_limit) &&
00559 relative_mass < cnsts.parameters(upper_ZAMS_mass_for_degenerate_core))
00560 return Helium_Dwarf;
00561
00562 else if (relative_mass >= cnsts.parameters(super_giant2neutron_star) &&
00563 core_mass > cnsts.parameters(carbon_dwarf_mass_limit))
00564 return Oxygen_Dwarf;
00565
00566 else
00567 return Carbon_Dwarf;
00568 }
00569