00001 
00002 
00003 
00004 
00005 #include "helium_star.h"
00006 #include "main_sequence.h"
00007 #include "hyper_giant.h"
00008 #include "sub_giant.h"
00009 #include "horizontal_branch.h"
00010 #include "super_giant.h"
00011 #include "hertzsprung_gap.h"
00012 
00013 helium_star::helium_star(main_sequence & m) : single_star(m) {
00014 
00015     delete &m;
00016 
00017     lose_envelope_decent();
00018 
00019     adjust_next_update_age();
00020 
00021 
00022     last_update_age = 0;
00023     relative_age = 0;
00024 
00025     
00026     real m_tot = get_total_mass();
00027     
00028     core_mass = 0;
00029     final_core_mass = final_CO_core_mass(m_tot);
00030     core_mass = COcore_mass = CO_core_mass();
00031     envelope_mass =  m_tot - core_mass;
00032 
00033 
00034 
00035 
00036     instantaneous_element();
00037     update();
00038 
00039     post_constructor();
00040     
00041 }
00042 
00043 helium_star::helium_star(hyper_giant & w) : single_star(w) {
00044 
00045     delete &w;
00046 
00047     lose_envelope_decent();
00048 
00049 
00050 
00051 
00052     real t_frac = (relative_age - main_sequence_time())
00053                / (nucleair_evolution_time()-main_sequence_time());
00054 
00055 
00056     adjust_next_update_age();
00057     relative_age = t_frac*next_update_age;
00058 
00059     
00060 
00061 
00062     last_update_age = relative_age;
00063 
00064     
00065     real m_tot = get_total_mass();
00066     
00067     core_mass = 0;
00068     final_core_mass = final_CO_core_mass(m_tot);
00069     core_mass = COcore_mass = CO_core_mass();
00070     envelope_mass =  m_tot - core_mass;
00071 
00072 
00073 
00074 
00075     instantaneous_element();
00076     update();
00077     
00078     post_constructor();
00079 
00080 }
00081 
00082 helium_star::helium_star(hertzsprung_gap & h) : single_star(h) {
00083 
00084     delete &h;
00085 
00086     lose_envelope_decent();
00087 
00088 
00089 
00090     last_update_age = 0.;
00091 
00092     adjust_next_update_age();
00093     relative_age = 0;
00094 
00095     
00096     real m_tot = get_total_mass();
00097     
00098     core_mass = 0;
00099     final_core_mass = final_CO_core_mass(m_tot);
00100     core_mass = COcore_mass = CO_core_mass();
00101     envelope_mass =  m_tot - core_mass;
00102 
00103 
00104 
00105     
00106     instantaneous_element();
00107     update();
00108     
00109     post_constructor();
00110 
00111 }
00112 
00113 helium_star::helium_star(sub_giant & g) : single_star(g) {
00114 
00115     delete &g;
00116     lose_envelope_decent();
00117 
00118 
00119 
00120     last_update_age = 0.;
00121 
00122     adjust_next_update_age();
00123     relative_age = 0;
00124 
00125     
00126     real m_tot = get_total_mass();
00127     
00128     core_mass = 0;
00129     final_core_mass = final_CO_core_mass(m_tot);
00130     core_mass = COcore_mass = CO_core_mass();
00131     envelope_mass =  m_tot - core_mass;
00132 
00133 
00134 
00135 
00136     instantaneous_element();
00137     update();
00138     
00139     post_constructor();
00140 
00141 }
00142 
00143 helium_star::helium_star(horizontal_branch & h) : single_star(h) {
00144 
00145     delete &h;
00146 
00147     lose_envelope_decent();
00148 
00149     real t_ms = main_sequence_time();
00150     real t_giant = t_ms + hertzsprung_gap_time(t_ms)
00151                  + base_giant_branch_time(t_ms);
00152     real t_he = helium_giant_time(t_ms);
00153     real t_frac = min(0.9,(relative_age - t_giant)/t_he);
00154 
00155 
00156     adjust_next_update_age();
00157     relative_age = t_frac* next_update_age;
00158 
00159 
00160 
00161     last_update_age = relative_age;
00162 
00163     
00164     real m_tot = get_total_mass();
00165     
00166     core_mass = 0;
00167     final_core_mass = final_CO_core_mass(m_tot);
00168     core_mass = COcore_mass = CO_core_mass();
00169     envelope_mass =  m_tot - core_mass;
00170 
00171 
00172 
00173 
00174     instantaneous_element();
00175     update();
00176     
00177     post_constructor();
00178 
00179  }
00180 
00181 #if 0
00182 void helium_star::adjust_initial_star() {
00183 
00184   update_wind_constant();
00185 
00186   if(relative_age<=0)
00187     relative_age = max(current_time, 0.0);
00188 }
00189 #endif
00190 
00191 
00192 void helium_star::adjust_next_update_age() {
00193 
00194   next_update_age = cnsts.parameters(helium_star_lifetime_fraction)
00195                   * helium_time();
00196 }
00197 
00198 void helium_star::instantaneous_element() {
00199 
00200   
00201     real temp;
00202     real m_tot = get_total_mass();
00203 
00204     temp = log10(m_tot)
00205       * (0.4509 - 0.1085*log10(m_tot)) + 4.7143;
00206     luminosity  = 8.33*temp - 36.8;
00207     temp = 1.e-3*pow(10., temp);
00208     luminosity  = pow(10., luminosity);
00209     effective_radius = radius = 33.45*sqrt(luminosity)/(temp*temp);
00210     core_radius  = 0.2*radius;
00211 
00212     if (envelope_mass <= 0) {
00213       effective_radius = radius  = core_radius;
00214     }
00215 
00216     if (final_core_mass <= 0)
00217       final_core_mass = final_CO_core_mass(m_tot);
00218 }
00219 
00220 void helium_star::evolve_element(const real end_time)
00221 {
00222     real dt = end_time - current_time;
00223     current_time = end_time;
00224     relative_age += dt;
00225     
00226     real m_tot = get_total_mass();
00227     if (relative_age>next_update_age) {
00228 
00229       core_mass = COcore_mass = CO_core_mass();
00230       envelope_mass = m_tot - core_mass;
00231         
00232       stellar_wind(dt);
00233 
00234       star_transformation_story(Helium_Giant);
00235       new helium_giant(*this);
00236       return;
00237     }
00238     else if (m_tot < cnsts.parameters(helium_dwarf_mass_limit) &&
00239              relative_mass < cnsts.parameters(
00240                              upper_ZAMS_mass_for_degenerate_core)) {
00241 
00242       
00243       core_mass = get_total_mass();
00244       envelope_mass = 0;
00245 
00246       if (is_binary_component()) 
00247         get_binary()->dump("binev.data", false);
00248       else
00249         dump("binev.data", false);
00250       
00251       star_transformation_story(Helium_Dwarf);
00252       new white_dwarf(*this);
00253       return;
00254     }
00255     else { 
00256         real tmp = log10(m_tot)
00257         * (0.4509 - 0.1085*log10(m_tot)) + 4.7143;
00258         luminosity  = pow(10., 8.33*tmp - 36.8);
00259         tmp = pow(1.e-3*pow(10., tmp), 2);
00260         radius = 33.45*sqrt(luminosity)/tmp;
00261         core_radius  = 0.2*radius;
00262 
00263 
00264 
00265         if (m_tot < 0.2) { 
00266           radius = 0.029 * pow(m_tot, -0.19);
00267           next_update_age = relative_age + cnsts.safety(maximum_timestep);
00268         }
00269 
00270         if (envelope_mass <= 0) {
00271             radius  = core_radius;
00272         }
00273     }
00274 
00275     core_mass = COcore_mass = CO_core_mass();
00276     
00277     envelope_mass = m_tot - core_mass;
00278     
00279     
00280     update();
00281     stellar_wind(dt);
00282 
00283 }
00284 
00285 void helium_star::update() {
00286     
00287     detect_spectral_features();
00288 
00289 
00290     effective_radius = radius;
00291 
00292 }
00293 
00294 #if 0
00295 void helium_star::create_remnant() {
00296 
00297 
00298 
00299 
00300 
00301 
00302 
00303 
00304 
00305 
00306 
00307 
00308 
00309 
00310 
00311 
00312 
00313 
00314 
00315 
00316 
00317 
00318 
00319 
00320 
00321 
00322 
00323 
00324 
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342      }
00343 #endif
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00367 
00368 
00369 
00370 star* helium_star::subtrac_mass_from_donor(const real dt, real& mdot) {
00371 
00372     mdot = relative_mass*dt/get_binary()->get_donor_timescale();
00373 
00374     mdot = mass_ratio_mdot_limit(mdot);
00375 
00376     if (envelope_mass >= mdot)
00377       envelope_mass -= mdot;
00378     else {
00379       mdot = envelope_mass;
00380       envelope_mass = 0;
00381       
00382       
00383       
00384     }
00385 
00386     return this;
00387 }
00388 
00389 star* helium_star::reduce_mass(const real mdot) {
00390 
00391     if (envelope_mass >= mdot)
00392       envelope_mass -= mdot;
00393     else {
00394       real mass_reduced = mdot;
00395       mass_reduced -= envelope_mass;
00396       envelope_mass = 0;
00397       if (core_mass>mass_reduced) {
00398         if (core_mass-mass_reduced<=cnsts.parameters(minimum_helium_star)) {
00399             core_mass -= mass_reduced;
00400 
00401 
00402 
00403         }
00404         else {
00405           core_mass -= mass_reduced;
00406           COcore_mass = core_mass;
00407         }
00408       }
00409       else {
00410         cerr<<"ERROR!:"<<endl;
00411         cerr<<"void helium_star::reduce_mass(mdot="
00412             <<mass_reduced<<")"<<endl;
00413         cerr<<"mdot exceeds helium core mass ("<<core_mass
00414             <<")"<<endl;
00415         cerr<<"Decision: Disintegrate helium star!"<<endl;
00416         
00417         
00418       }
00419     }
00420     
00421     return this;
00422 }
00423 
00424 
00425 real helium_star::add_mass_to_accretor(const real mdot) {
00426 
00427         if (mdot<0) {
00428            cerr << "helium_star::add_mass_to_accretor(mdot=" 
00429                  << mdot << ")"<<endl;
00430            cerr << "mdot (" << mdot << ") smaller than zero!" << endl;
00431            return 0;
00432         }
00433 
00434         adjust_accretor_age(mdot);
00435         if (relative_mass<get_total_mass() + mdot)
00436           relative_mass = get_total_mass() + mdot;
00437 
00438 
00439 
00440         
00441         envelope_mass += mdot;
00442         
00443         set_spec_type(Accreting);
00444         
00445         return mdot;
00446 
00447 }
00448 
00449 real helium_star::add_mass_to_accretor(real mdot, const real dt) {
00450 
00451         if (mdot<0) {
00452            cerr << "helium_star::add_mass_to_accretor(mdot=" 
00453                  << mdot << ")"<<endl;
00454            cerr << "mdot (" << mdot << ") smaller than zero!" << endl;
00455            return 0;
00456         }
00457 
00458         mdot = accretion_limit(mdot, dt);
00459         adjust_accretor_age(mdot);
00460         if (relative_mass<get_total_mass() + mdot)
00461            relative_mass = get_total_mass() + mdot;
00462 
00463 
00464 
00465 
00466         envelope_mass += mdot;
00467 
00468         set_spec_type(Accreting);
00469 
00470         return mdot;
00471 
00472      }
00473 
00474 real helium_star::accretion_limit(const real mdot, const real dt) {
00475        
00476         real eddington = 1.5e-08*cnsts.parameters(solar_radius)*radius*dt;
00477 
00478         if(mdot>=eddington) return eddington;
00479 
00480         return mdot;
00481 }
00482 
00483 
00484 
00485 void helium_star::adjust_accretor_age(const real mdot,
00486                                       const bool rejuvenate) {
00487 
00488     relative_age *= (1-pow(mdot/(get_total_mass()+mdot),
00489                     cnsts.parameters(rejuvenation_exponent)));
00490 
00491 }
00492 
00493 
00494 
00495 real helium_star::zeta_adiabatic() {
00496 
00497   real z = 15;
00498   
00499   return z;
00500 
00501 }
00502 
00503 real helium_star::zeta_thermal() {
00504 
00505 
00506   if (get_total_mass() < 0.2 ) {
00507     return -0.19;
00508   } else {
00509     return 1;
00510   }
00511 }
00512 
00513 real helium_star::final_CO_core_mass(const real initial_mass) {
00514 
00515   
00516   
00517   
00518   
00519   real final_coremass_fraction;
00520   if(relative_mass >= cnsts.parameters(maximum_main_sequence))
00521     final_coremass_fraction = 1;
00522   else if(initial_mass <= 0.8) 
00523     final_coremass_fraction = 1;
00524   else if(initial_mass >= cnsts.parameters(helium2neutron_star)) 
00525     final_coremass_fraction = 0.65;
00526   else 
00527     final_coremass_fraction = 1 - 0.32 * (initial_mass - 0.8);
00528 
00529   return final_coremass_fraction*initial_mass;
00530 }
00531 
00532 real helium_star::CO_core_mass() {
00533 
00534   real m_core = final_core_mass * relative_age/next_update_age;
00535   m_core = max(core_mass, m_core);
00536 
00537   return min(m_core, get_total_mass());
00538 }
00539 
00540 void helium_star::stellar_wind(const real dt) {
00541 
00542 
00543 
00544             real kappa = pow(get_total_mass(),2.5);
00545 
00546 
00547 
00548 
00549 
00550 
00551 
00552         if(get_total_mass()>core_mass) {
00553 
00554 
00555 
00556 
00557 
00558           real wind_mass = 0.05*dt*kappa;
00559 
00560           real m = get_total_mass();
00561           real constant = 0.05;
00562 
00563           real m_next = pow((pow(m,-1.5) + 1.5*constant*dt),-1/1.5);
00564           wind_mass = m - m_next;
00565 
00566 
00567 
00568 
00569           if (get_total_mass() < 2.5 ) wind_mass = 0.;
00570 
00571            if (wind_mass>=envelope_mass) {
00572               wind_mass = envelope_mass;
00573               radius = core_radius;
00574            }
00575 
00576            if (is_binary_component())
00577               get_binary()->adjust_binary_after_wind_loss(
00578                           this, wind_mass, dt);
00579            else
00580               reduce_mass(wind_mass);
00581               return;
00582         }
00583    } 
00584 
00585 
00586 real helium_star::gyration_radius_sq() {
00587 
00588   return cnsts.parameters(radiative_star_gyration_radius_sq); 
00589 }
00590 
00591 
00592 
00593 void helium_star::update_wind_constant() {
00594 
00595   wind_constant = (1 - cnsts.parameters(helium_star_final_core_fraction))
00596                       * get_total_mass();
00597 }
00598 
00599 stellar_type helium_star::get_element_type() {
00600   if (envelope_mass <= 0) 
00601     return Carbon_Star;
00602   else
00603     return Helium_Star;
00604 }
00605 
00606 real helium_star::temperature() {
00607   real T_eff = cnsts.parameters(Tsun)
00608              * sqrt(sqrt(luminosity)/effective_radius);
00609   return T_eff;
00610   
00611 }