00001 #include "hertzsprung_gap.h"
00002 #include "main_sequence.h"
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016      hertzsprung_gap::hertzsprung_gap(main_sequence & m) : single_star(m) {
00017 
00018       delete &m;        
00019 
00020       real m_tot    = get_total_mass();
00021       core_mass     = TAMS_helium_core_mass();
00022       envelope_mass = m_tot - core_mass;
00023       core_radius   = helium_core_radius();
00024 
00025 
00026 
00027       last_update_age = next_update_age;
00028 
00029       adjust_next_update_age();
00030 
00031       instantaneous_element();
00032       update();
00033       
00034       post_constructor();
00035    }
00036 
00037 void hertzsprung_gap::instantaneous_element() {
00038 
00039       real alpha, beta, gamma, delta;
00040 
00041       real log_mass = log10(relative_mass);
00042 
00043       if (relative_mass>1.334) {
00044          alpha = 0.1509 + 0.1709*log_mass;
00045          beta  = 0.06656 - 0.4805*log_mass;
00046          gamma = 0.007395 + 0.5083*log_mass;
00047          delta = (0.7388*pow(relative_mass, 1.679)
00048                - 1.968*pow(relative_mass, 2.887))
00049                / (1.0 - 1.821*pow(relative_mass, 2.337));
00050        }
00051        else {
00052           alpha = 0.08353 + 0.0565*log_mass;
00053           beta  = 0.01291 + 0.2226*log_mass;
00054           gamma = 0.1151 + 0.06267*log_mass;
00055           delta = pow(relative_mass, 1.25)
00056                 * (0.1148 + 0.8604*relative_mass*relative_mass)
00057                 / (0.04651 + relative_mass*relative_mass);
00058        }
00059 
00060       real l_bgb  = base_giant_branch_luminosity();
00061       real rt = delta*pow(10., (alpha + beta + gamma));
00062           
00063       luminosity = l_bgb;
00064       
00065       
00066       
00067 
00068       radius     = rt;
00069 
00070    }
00071 
00072 #if 0
00073 void hertzsprung_gap::adjust_initial_star() {
00074 
00075   if(relative_age<=0)
00076     relative_age = max(main_sequence_time(), relative_age);
00077 }
00078 #endif
00079 
00080 
00081 
00082 void hertzsprung_gap::evolve_element(const real end_time) {
00083 
00084 
00085 
00086       real alpha, beta, gamma, delta;
00087 
00088       real dt = end_time - current_time;
00089       current_time = end_time;
00090       relative_age += dt;
00091 
00092       real log_mass = log10(relative_mass);
00093 
00094       if (relative_mass>1.334) {
00095          alpha = 0.1509 + 0.1709*log_mass;
00096          beta  = 0.06656 - 0.4805*log_mass;
00097          gamma = 0.007395 + 0.5083*log_mass;
00098          delta = (0.7388*pow(relative_mass, 1.679)
00099                - 1.968*pow(relative_mass, 2.887))
00100                / (1.0 - 1.821*pow(relative_mass, 2.337));
00101        }
00102        else {
00103           alpha = 0.08353 + 0.0565*log_mass;
00104           beta  = 0.01291 + 0.2226*log_mass;
00105           gamma = 0.1151 + 0.06267*log_mass;
00106           delta = pow(relative_mass, 1.25)
00107                 * (0.1148 + 0.8604*relative_mass*relative_mass)
00108                 / (0.04651 + relative_mass*relative_mass);
00109        }
00110 
00111        real t_ms   = main_sequence_time();
00112       
00113        if (relative_age<=next_update_age) {
00114 
00115           if(relative_age<t_ms) relative_age = t_ms; 
00116           real t_hg   = hertzsprung_gap_time(t_ms);
00117           real l_g    = giant_luminosity();
00118           real l_bgb  = base_giant_branch_luminosity();
00119 
00120           real rt = delta*pow(10., (alpha + beta + gamma));
00121           real rg = (0.25*pow(l_g, 0.4) + 0.8*pow(l_g, 0.67))
00122                   / pow(relative_mass, 0.27);
00123           real ff = (relative_age - t_ms)/t_hg;
00124           luminosity = l_bgb*pow(l_g/l_bgb, ff);
00125           radius = rt*pow(rg/rt, ff);
00126 
00127           evolve_core_mass(dt);
00128        }
00129        else {
00130 
00131          
00132          
00133          
00134          if (base_giant_branch_time(t_ms)) {
00135           star_transformation_story(Sub_Giant);
00136           new sub_giant(*this);
00137           return;
00138          }
00139          else {
00140           star_transformation_story(Horizontal_Branch);
00141           new horizontal_branch(*this);
00142           return;
00143         }
00144        }
00145 
00146        update();
00147        stellar_wind(dt);
00148 }
00149 
00150 star* hertzsprung_gap::reduce_mass(const real mdot) {
00151 
00152       if (envelope_mass<=mdot) {
00153         envelope_mass = 0;
00154 
00155         
00156         
00157         
00158         if (get_total_mass() < cnsts.parameters(helium_dwarf_mass_limit) &&
00159             relative_mass < cnsts.parameters(
00160                             upper_ZAMS_mass_for_degenerate_core)) {
00161           star_transformation_story(Helium_Dwarf);
00162           return dynamic_cast(star*, new white_dwarf(*this));
00163         } 
00164         else {
00165           star_transformation_story(Helium_Star);
00166           return dynamic_cast(star*, new helium_star(*this));
00167         }
00168       }
00169 
00170       envelope_mass -= mdot;
00171       return this;
00172    }
00173 
00174 star* hertzsprung_gap::subtrac_mass_from_donor(const real dt, real& mdot) {
00175 
00176 
00177       mdot = relative_mass*dt/get_binary()->get_donor_timescale();
00178 
00179       mdot = mass_ratio_mdot_limit(mdot);
00180 
00181       if (envelope_mass<=mdot) {
00182 
00183          mdot = envelope_mass;
00184          envelope_mass = 0;
00185 
00186         
00187         
00188         
00189         if (get_total_mass() < cnsts.parameters(helium_dwarf_mass_limit) &&
00190             relative_mass < cnsts.parameters(
00191                             upper_ZAMS_mass_for_degenerate_core)) {
00192           star_transformation_story(Helium_Dwarf);
00193           return dynamic_cast(star*, new white_dwarf(*this));
00194         } 
00195         else {
00196           star_transformation_story(Helium_Star);
00197           return dynamic_cast(star*, new helium_star(*this));
00198         }
00199       }
00200 
00201 
00202       adjust_donor_radius(mdot);
00203 
00204       envelope_mass -= mdot;
00205       return this;
00206    }
00207 
00208 
00209 void hertzsprung_gap::adjust_accretor_age(const real mdot, const bool rejuvenate=true) {
00210 
00211 
00212       real m_rel_new;
00213       real m_tot_new = get_total_mass() + mdot;
00214       if (m_tot_new>relative_mass)
00215          m_rel_new = m_tot_new;
00216       else m_rel_new = relative_mass;
00217 
00218       real t_ms_old = main_sequence_time();
00219       real t_hg_old = hertzsprung_gap_time(t_ms_old);
00220 
00221       real t_ms_new = main_sequence_time(m_rel_new);
00222       real t_hg_new = hertzsprung_gap_time(m_rel_new, t_ms_old);
00223 
00224       real dtime = relative_age - t_ms_old;
00225 
00226 
00227       last_update_age = t_ms_new;
00228 
00229       relative_age = t_ms_new 
00230                    + dtime*(t_hg_new/t_hg_old);
00231       if (rejuvenate)
00232          relative_age *= rejuvenation_fraction(mdot/m_tot_new); 
00233 
00234       relative_age = max(relative_age, 
00235                          last_update_age + cnsts.safety(minimum_timestep)); 
00236       
00237       
00238       
00239    }
00240 
00241 
00242 
00243 real hertzsprung_gap::zeta_adiabatic() {
00244 
00245 
00246 #if 0
00247       real z;
00248 
00249       real x = core_mass/get_total_mass();
00250       real A = -0.220823;
00251       real B = -2.84699;
00252       real C = 32.0344;
00253       real D = -75.6863;
00254       real E = 57.8109;
00255 
00256       if (get_relative_mass()<=0.4)
00257          z = -cnsts.mathematics(one_third);
00258       else if (low_mass_star())
00259          z = A + x*(B + x*(C + x*(D + x*E)));
00260       else if (medium_mass_star())
00261          z = 2.25;                 
00262       else                         
00263          z = 2.25;                 
00264 #endif
00265       real z = 4; 
00266                      
00267 
00268 
00269       return z;
00270    }
00271 
00272 
00273 real hertzsprung_gap::zeta_thermal() {
00274 
00275       real z;
00276 
00277       if (get_relative_mass()<=0.4)
00278          z = 0;         
00279       else if (low_mass_star())
00280          z = -2;        
00281       else              
00282          z = -2;        
00283 
00284       return z;
00285    }
00286 
00287 void hertzsprung_gap::adjust_next_update_age() {
00288    
00289       real t_ms = main_sequence_time();
00290       if (relative_age<t_ms)
00291          relative_age = t_ms;
00292       next_update_age = t_ms + hertzsprung_gap_time(t_ms);
00293 }
00294 
00295 void hertzsprung_gap::detect_spectral_features() {
00296 
00297 
00298       single_star::detect_spectral_features();
00299 
00300       if (accreted_mass>=cnsts.parameters(B_emission_star_mass_limit))
00301         spec_type[Emission]=Emission;
00302    }
00303 
00304 #if 0
00305 real hertzsprung_gap::stellar_radius(const real mass, const real age_max) {
00306 
00307       real alpha, beta, gamma, delta;
00308       real t_ms   = main_sequence_time(mass);
00309       real age = max(t_ms, age_max);            
00310       real t_hg   = hertzsprung_gap_time(t_ms);
00311 
00312       real log_mass = log10(mass);
00313 
00314       if (mass>1.334) {
00315          alpha = 0.1509 + 0.1709*log_mass;
00316          beta  = 0.06656 - 0.4805*log_mass;
00317          gamma = 0.007395 + 0.5083*log_mass;
00318          delta = (0.7388*pow(mass, 1.679)
00319                - 1.968*pow(mass, 2.887))
00320                / (1.0 - 1.821*pow(mass, 2.337));
00321        }
00322        else {
00323           alpha = 0.08353 + 0.0565*log_mass;
00324           beta  = 0.01291 + 0.2226*log_mass;
00325           gamma = 0.1151 + 0.06267*log_mass;
00326           delta = pow(mass, 1.25)
00327                 * (0.1148 + 0.8604*mass*mass)
00328                 / (0.04651 + mass*mass);
00329        }
00330 
00331        real l_g    = giant_luminosity(mass);
00332 
00333        real rt = delta*pow(10., (alpha + beta + gamma));
00334        real rg = (0.25*pow(l_g, 0.4) + 0.8*pow(l_g, 0.67))
00335                / pow(mass, 0.27);
00336        real ff = (age - t_ms)/t_hg;
00337        real r_hg = rt*pow(rg/rt, ff);
00338 
00339        return r_hg;
00340    }
00341 #endif
00342 
00343 
00344 
00345 
00346 
00347 real hertzsprung_gap::gyration_radius_sq() {
00348 
00349   return cnsts.parameters(radiative_star_gyration_radius_sq); 
00350 }
00351 
00352 
00353 
00354 real hertzsprung_gap::TAMS_helium_core_mass() {
00355 
00356   
00357   
00358   real mc = (0.11*pow(relative_mass,1.2)
00359           + 7.e-5*pow(relative_mass,4))
00360           / (1+ 2e-4*pow(relative_mass, 3));
00361 
00362   
00363   
00364   
00365   
00366   
00367   
00368   
00369 
00370   
00371   
00372   
00373   return min(max(mc,core_mass), 
00374              get_total_mass()-cnsts.safety(minimum_mass_step));
00375 
00376 }
00377 
00378 void hertzsprung_gap::evolve_core_mass(const real dt) {
00379 
00380   
00381   real X = cnsts.parameters(hydrogen_fraction);
00382   real delta_mcore = luminosity*dt
00383                    / (X * cnsts.parameters(energy_to_mass_in_internal_units));
00384 
00385 
00386   delta_mcore = min(delta_mcore, envelope_mass);
00387   
00388   
00389   
00390   
00391 
00392   if (delta_mcore<0) {
00393       PRC(luminosity);PRC(dt);PRL(delta_mcore);
00394       cerr << "Core mass increas is negative in hertzsprung_gap:evolve_core_mass()"<<endl;
00395       delta_mcore = 0;
00396       dump(cerr, false);
00397       exit(-1);
00398       return;
00399   }
00400 
00401   envelope_mass -= delta_mcore; 
00402   core_mass += delta_mcore;
00403 }
00404 
00405 
00406 
00407 
00408 void hertzsprung_gap::update_wind_constant() {
00409 
00410 
00411   if (relative_mass >= cnsts.parameters(super_giant2neutron_star)) {
00412 
00413     real meader_fit_dm = 0.01*pow(relative_mass,2.);
00414     
00415     if (relative_mass < 85)
00416       wind_constant = meader_fit_dm;
00417     else {
00418       real final_mass = 30;
00419       wind_constant = relative_mass - final_mass;
00420     }
00421 
00422   } 
00423   else { 
00424 
00425     wind_constant = 0.01*relative_mass;
00426   }
00427 
00428   wind_constant = max(wind_constant, 0.0);
00429 }