Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

white_dwarf.C

Go to the documentation of this file.
00001 //
00002 // white_dwarf.C
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 // (GN+SPZ May  4 1999) last update age is time of previous type change
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 // (GN+SPZ May  4 1999) last update age is time of previous type change
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 // (GN+SPZ May  4 1999) last update age is time of previous type change
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 // (GN+SPZ May  4 1999) last update age is time of previous type change
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 // (GN+SPZ May  4 1999) last update age is time of previous type change
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 //cerr << "white_dwarf::instantaneous_element"<<endl;
00160 
00161         next_update_age = relative_age + cnsts.safety(maximum_timestep);
00162 
00163         luminosity = 40;
00164         // m_rel may not become larger than M_Ch
00165 //      real m_rel = min(0.99, core_mass/cnsts.parameters(Chandrasekar_mass));
00166 
00167         // Nauenberg, M, 1972, Apj 175, 417
00168         // mu=4.039 is the mean molecular weight.
00169         real mu = 2.;
00170 
00171         effective_radius =
00172         core_radius      =
00173         radius           = white_dwarf_radius(core_mass, relative_age);
00174           //               min(0.1, (0.0225/mu)*
00175           //               sqrt(1./pow(m_rel, cnsts.mathematics(two_third))
00176           //               - pow(m_rel, cnsts.mathematics(two_third))));
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 // done in add_mass_to_accretor
00187 //        accrete_from_envelope(dt);
00188 
00189         if (core_mass > cnsts.parameters(Chandrasekar_mass) ||
00190             core_mass <= cnsts.safety(minimum_mass_step)) {
00191             // || accreted_mass > 0.2) {
00192             // (GN Mar 26 1999) test edge lid detanation 
00193             // needs more research
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           // new neutron_star(*this);    // AIC
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           // (GN May  4 1999) fit to Driebe et al 1999
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 //      real m_rel = min(0.99, core_mass/cnsts.parameters(Chandrasekar_mass));
00223 
00224            // Nauenberg, M, 1972, Apj 175, 417
00225            // mu=4.039 is the mean molecular weight.
00226            real mu = 2.;
00227            core_radius =
00228              radius           = white_dwarf_radius(core_mass, relative_age);
00229 
00230 //             radius = min(0.1, (0.0225/mu)
00231 //                  * sqrt(1./pow(m_rel, cnsts.mathematics(two_third))
00232 //                    - pow(m_rel, cnsts.mathematics(two_third))));
00233 
00234         // (GN+SPZ May  3 1999) critical mass for nova (Livio 1993; Saas-Fee)
00235            real m_crit = 1.7e-4*pow(get_total_mass(),-0.7)
00236                        * pow(69.9*radius,2.8); // radius in 10^9 cm
00237 
00238         if (envelope_mass >= m_crit) 
00239            thermo_nucleair_flash(dt);
00240 
00241 
00242 //         if (envelope_mass >= core_mass
00243 //                           * cnsts.parameters(thermo_nuclear_flash))
00244 //           thermo_nucleair_flash(dt);
00245        
00246            update();
00247 }
00248 
00249 void white_dwarf::update() {
00250 
00251         detect_spectral_features();
00252 // (GN+SPZ May  4 1999) last_update_age now used as time of last type change
00253 //  last_update_age = relative_age;
00254         effective_radius = max(effective_radius, radius);
00255 
00256 }
00257 
00258 
00259 // (SPZ+GN: 27 Jul 2000) Gijs sais is better: Nelemans et al 2000
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; // radius for M < 0.2 equal to M = 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      //         Nauenberg, M, 1972, Apj 175, 417
00285      //         mu=4.039 is the mean molecular weight.
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 //              Spiral in or dwarf nova
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) //was 2.5 
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 // (GN+SPZ May  3 1999)
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 // (GN+SPZ May  3 1999) test helium accretion and steady burning accumulate
00429 // helium on core of wd. Steady burning between maximum_steady_burning
00430 // and minimum_steady_burning 
00431 // (Sienkewicz 1980, described in van den Heuvel et al. 1992) 
00432 // If this layer becomes more heavy than 0.2 Msun: boom! see evolve_element
00433 
00434         if (is_binary_component() &&
00435             get_companion()->hydrogen_envelope_star() 
00436             && mdot < minimum_steady_burning(dt)) {// normal accretion
00437 
00438           envelope_mass += mdot;
00439         } 
00440         else { // helium accretion or steady burning
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 // (GN Mar 30 1999) steady burning limit 
00474 // (Sienkewicz 1980, described in van den Heuvel et al. 1992)
00475 real  white_dwarf::maximum_steady_burning(const real dt) {
00476 
00477 // Fit to Iben & Tutukov 1989
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 // Fit to Iben & Tutukov 1989
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      // Based on white dwarf mass radius relation.
00513      // zeta = (m/r)dr/dm;
00514   
00515      return -cnsts.mathematics(one_third);
00516 }
00517 
00518 star* white_dwarf::merge_elements(star* str) {
00519 
00520      envelope_mass = 0;         //Destroy disc.
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 

Generated at Sun Feb 24 09:57:20 2002 for STARLAB by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001