Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

black_hole.C

Go to the documentation of this file.
00001 //
00002 // black_hole.C
00003 //
00004 
00005 #include "black_hole.h"
00006 #include "hyper_giant.h"
00007 #include "super_giant.h"
00008 #include "thorne_zytkow.h"
00009 #include "helium_giant.h"
00010 #include "neutron_star.h"
00011 
00012 // ANSI C++ first creates the base class before the dreived classes are
00013 // created. If this is done in another order we are in deep shit.
00014 
00015 black_hole::black_hole(hyper_giant & w) : single_star(w) {
00016 
00017       delete &w;
00018 
00019       suddenly_lost_mass = 0;
00020       real m_tot = get_total_mass();
00021 
00022       core_mass = black_hole_mass();
00023       envelope_mass = m_tot - core_mass;
00024       
00025 // (GN+SPZ May  4 1999) last update age is time of previous type change
00026       last_update_age = next_update_age;
00027 
00028       relative_age = 0;
00029 
00030       bool hit_companion = super_nova();
00031       post_supernova_story(); 
00032       
00033       instantaneous_element();
00034       update();
00035       
00036       if (hit_companion)
00037          direct_hit();
00038 
00039       post_constructor();
00040 
00041 
00042       if (is_binary_component()) {
00043         get_binary()->set_first_contact(false);
00044         get_companion()->set_spec_type(Accreting, false);
00045         get_binary()->dump("binev.data", false);
00046       }
00047       else {
00048         dump("binev.data", false);
00049       }
00050 }
00051 
00052 black_hole::black_hole(super_giant & g) : single_star(g) {
00053 
00054       delete &g;
00055 
00056       suddenly_lost_mass = 0;
00057       real m_tot = get_total_mass();
00058       core_mass = black_hole_mass();
00059       envelope_mass = m_tot - core_mass;
00060 
00061 // (GN+SPZ May  4 1999) last update age is time of previous type change
00062       last_update_age = next_update_age;
00063 
00064       relative_age = 0;
00065 
00066       bool hit_companion = super_nova();
00067       post_supernova_story(); 
00068 
00069       instantaneous_element();
00070       update();
00071 
00072       if (hit_companion)
00073          direct_hit();
00074  
00075       post_constructor();
00076 
00077       if (is_binary_component()) {
00078         get_binary()->set_first_contact(false);
00079         get_companion()->set_spec_type(Accreting, false);
00080         get_binary()->dump("binev.data", false);
00081       }
00082       else {
00083         dump("binev.data", false);
00084       }
00085   }
00086 
00087 black_hole::black_hole(thorne_zytkow & t) : single_star(t) {
00088 
00089       delete &t;
00090 
00091       magnetic_field  = 0;
00092       rotation_period = 0;
00093 
00094       //  TZO core is the black-hole itself!
00095       suddenly_lost_mass = 0;
00096       relative_age = 0;
00097 
00098       bool hit_companion = super_nova();
00099       post_supernova_story(); 
00100 
00101 // (GN+SPZ May  4 1999) last update age is time of previous type change
00102       last_update_age = next_update_age;
00103 
00104       instantaneous_element();
00105       update();
00106 
00107       if (hit_companion)
00108          direct_hit();
00109 
00110       post_constructor();
00111 
00112       if (is_binary_component()) {
00113         get_binary()->set_first_contact(false);
00114         get_companion()->set_spec_type(Accreting, false);
00115         get_binary()->dump("binev.data", false);
00116       }
00117       else {
00118         dump("binev.data", false);
00119       }
00120 
00121 }
00122 
00123 black_hole::black_hole(helium_giant & h) : single_star(h) {
00124 
00125       delete &h;
00126 
00127       suddenly_lost_mass = 0;
00128       real m_tot = get_total_mass();
00129       core_mass = black_hole_mass();
00130       envelope_mass = m_tot - core_mass;
00131 
00132 // (GN+SPZ May  4 1999) last update age is time of previous type change
00133       last_update_age = next_update_age;
00134 
00135       relative_age = 0;
00136 
00137       bool hit_companion = super_nova();
00138       post_supernova_story(); 
00139 
00140       instantaneous_element();
00141       update();
00142 
00143       if (hit_companion)
00144          direct_hit();
00145 
00146       post_constructor();
00147       if (is_binary_component()) {
00148         get_binary()->set_first_contact(false);
00149         get_companion()->set_spec_type(Accreting, false);
00150         get_binary()->dump("binev.data", false);
00151       }
00152       else {
00153         dump("binev.data", false);
00154       }
00155 }
00156 
00157 black_hole::black_hole(neutron_star & n) : single_star(n) {
00158 
00159       delete &n;
00160 
00161       magnetic_field  = 0;
00162       rotation_period = 0;
00163 
00164       suddenly_lost_mass = 0;
00165 
00166 // (GN+SPZ May  4 1999) last update age is time of previous type change
00167       last_update_age = next_update_age;
00168 
00169       relative_age = 0;
00170 
00171       bool hit_companion = super_nova();
00172       post_supernova_story(); 
00173 
00174       instantaneous_element();
00175 
00176       if (hit_companion)
00177          direct_hit();
00178 
00179       post_constructor();
00180 
00181       if (is_binary_component()) {
00182         get_binary()->set_first_contact(false);
00183         get_companion()->set_spec_type(Accreting, false);
00184         get_binary()->dump("binev.data", false);
00185       }
00186       else {
00187         dump("binev.data", false);
00188       }
00189 
00190 }
00191 
00192 #if 0
00193 // Initial black_hole should be properly initialized.
00194 void black_hole::adjust_initial_star() {
00195 
00196   if (core_mass<=0) {
00197     core_mass = get_total_mass();
00198     envelope_mass = 0;
00199   }
00200   
00201   if (relative_age<=0) 
00202     relative_age = max(current_time, 0.0);
00203   effective_radius = core_radius = radius
00204                    = cnsts.parameters(kanonical_neutron_star_radius);
00205 
00206   if (relative_mass<cnsts.parameters(super_giant2black_hole)) {
00207     cerr<<"Black hole with low mass!"
00208         <<"\n should be turned into a neutron star"
00209         <<"\nadopt minimum BH relative mass"<<endl;
00210     relative_mass = cnsts.parameters(super_giant2black_hole);
00211     return;
00212   }
00213 }
00214 #endif
00215 
00216 real black_hole::get_radius() {
00217 
00218     real r_eff = radius;
00219     if (is_binary_component() &&
00220         !get_companion()->remnant()) {
00221 
00222         real m_sec = get_companion()->get_total_mass();
00223         real r_sec = get_companion()->get_radius();
00224         real r_tide = r_sec * (1 + pow(get_total_mass()/m_sec,
00225                                        cnsts.mathematics(one_third)));
00226         r_eff = r_tide;
00227 
00228     }
00229 
00230     return r_eff;
00231 }
00232 
00233 void black_hole::instantaneous_element() {
00234 
00235       next_update_age = relative_age + cnsts.safety(maximum_timestep);
00236 
00237       magnetic_field  = 0;
00238       rotation_period = 0;
00239       
00240       luminosity = 0.01;
00241 
00242       core_radius = effective_radius = radius = 4.25e-6*core_mass;
00243 
00244       update();
00245    }
00246 
00247 // Not much to evolve about a black hole.
00248 // Fixed radius, no wind, no nothing really low budget.
00249 void black_hole::evolve_element(const real end_time) {
00250 
00251       real dt = end_time - current_time;
00252       current_time = end_time;
00253       relative_age += dt;
00254 
00255       next_update_age = relative_age + cnsts.safety(maximum_timestep);
00256       accrete_from_envelope(dt);
00257 
00258       luminosity = 0.01;
00259 
00260       core_radius = radius = 4.25e-6*core_mass;
00261 
00262       update();
00263    }
00264 
00265 void black_hole::update() {
00266 
00267       detect_spectral_features();
00268       
00269 // (GN+SPZ May  4 1999) last_update_age now used as time of last type change
00270 //  last_update_age = relative_age;
00271       effective_radius = radius;
00272    }
00273 
00274 // Binding energy for a black hole.
00275 // When no mass loss during a super-nova (collapse from a neutron star to
00276 // a blck hole) the binading energy is thought to be released in the 
00277 // explosion.
00278 real black_hole::aic_binding_energy() {
00279 
00280       real GM2_RC2 = 3*cnsts.physics(G)*pow(cnsts.parameters(solar_mass)
00281                    / cnsts.physics(C), 2)/(5*cnsts.parameters(solar_radius));
00282       return GM2_RC2*core_mass/(4.25e-6*cnsts.parameters(solar_mass));
00283    }
00284 
00285 real black_hole::black_hole_mass() {
00286 
00287   // Relation used if helium2black_hole=15 and
00288   //                  super_giant2black_hole=40
00289   // (SPZ+GN:24 Sep 1998)
00290   // real m = (0.35*relative_mass - 12);
00291 
00292 // (GN+SPZ May 12 1999) was nice try, but seemt to be a bit unrealistic
00293 // Try simple MBH = frac * MHe with frac = 0.5
00294 
00295 //  real m = 0.5 * get_total_mass();
00296 
00297     //approximation to Fryer & Kalogera 2001
00298     real m = get_total_mass();
00299     if(m<40) {
00300         m = min(m, core_mass);
00301     }
00302 
00303     return m;
00304 
00305 }
00306 
00307 // Allow black_hole star to accrete from a disc.
00308 // Mass accreted by the hole is first put into a storage disk
00309 // and on a slower rate accreted onto the hole.
00310 // The accretion effeciency BH_CORE_ACCRETION is defined in
00311 // constants.h and has a magnitude of a few percent.
00312 void black_hole::accrete_from_envelope(const real dt) {
00313 
00314       real mdot = cnsts.parameters(black_hole_accretion_limit)
00315                 * accretion_limit(envelope_mass, dt);
00316 
00317       if (mdot>0) {
00318 
00319         set_spec_type(Accreting);
00320         core_mass += mdot;
00321         envelope_mass -= mdot;
00322       }
00323       else
00324         set_spec_type(Accreting, false);
00325 }
00326 
00327 real black_hole::add_mass_to_accretor(const real mdot) {
00328 
00329 //              Increase envelope_mass of black hole.
00330       envelope_mass += mdot;
00331       relative_mass = max(relative_mass, get_total_mass());
00332 
00333       return mdot;
00334    }
00335 
00336 real black_hole::add_mass_to_accretor(real mdot, const real dt) {
00337 
00338       mdot = accretion_limit(mdot, dt);
00339 
00340       envelope_mass += mdot;
00341       relative_mass = max(relative_mass, get_total_mass());
00342 
00343       return mdot;
00344    }
00345 
00346 // Accretion is limited by the Eddington luminosity
00347 real black_hole::accretion_limit(const real mdot, const real dt) {
00348 
00349       real eddington = 1.5e-08*cnsts.parameters(solar_radius)*radius*dt;
00350       if (cnsts.parameters(hyper_critical))
00351         eddington *= 1.e8;
00352       
00353       return min(eddington, mdot);
00354 }
00355 
00356 // A black hole is generally not a donor.
00357 star* black_hole::subtrac_mass_from_donor(const real dt, real& mdot) {
00358 
00359       mdot = accretion_limit(envelope_mass, dt);
00360       mdot = mass_ratio_mdot_limit(mdot);
00361 
00362       envelope_mass -= mdot;
00363       return this;
00364 }
00365 
00366 
00367 star* black_hole::merge_elements(star* str) {
00368 
00369       envelope_mass = 0;
00370       real merger_core = str->get_core_mass();
00371       real merger_env = str->get_envelope_mass();
00372 
00373       if(get_total_mass()<100) {
00374           add_mass_to_accretor(merger_env);
00375           core_mass += merger_core;
00376       }
00377       else {
00378           core_mass += merger_core + merger_env;
00379       }
00380       
00381       relative_mass = max(relative_mass, get_total_mass());
00382 
00383       spec_type[Merger]=Merger;
00384       instantaneous_element();
00385 
00386       return this;
00387    }
00388 
00389 // Tricky, especially in higher order system.
00390 // One of the few routines that requires the random number generator.
00391 // random numbers:
00392 //      kick_velocity,
00393 //      theta (kick-angel in orbital plane),
00394 //      phi   (kick-angel perpendicular to orbital plane).
00395 // separation is determined by solving Keplers equation for the
00396 // Eccentric anomaly taking the mean anomaly randomly.
00397 //
00398 // Note that a black hole does not receive a kick!!
00399 //
00400 // Return value is boolian whather or not the remnant colescence
00401 // with its companion.
00402 bool black_hole::super_nova() {
00403 
00404       suddenly_lost_mass = envelope_mass;
00405 
00406       bool hit_companion = FALSE;
00407 
00408       // Impulse kick
00409       real impulse_kick = 
00410            cnsts.parameters(kanonical_neutron_star_mass)/core_mass;
00411 
00412       // Energy kick
00413       // real energy_kick = sqrt(impulse_kick);
00414   
00415   
00416       real v_kick  = cnsts.super_nova_kick(no_velocity_kick);
00417 
00418 //      real v_kick  = impulse_kick
00419 //                     * cnsts.super_nova_kick(Paczynski_velocity_kick);
00420 
00421       real theta_kick = acos(1-2*random_angle(0, 1));
00422       real phi_kick   = random_angle(0, cnsts.mathematics(two_pi));
00423 
00424 //      cerr << "Supernova kick v = " << v_kick << " [km/s]" << endl;
00425 
00426     if (get_use_hdyn()) {
00427 
00428       // Transform 1D kick velocity to 3D space velocity for dynamics.
00429       real x_kick = v_kick*sin(theta_kick)*cos(phi_kick);
00430       real y_kick = v_kick*sin(theta_kick)*sin(phi_kick);
00431       real z_kick = v_kick*cos(theta_kick);
00432       vector kick_velocity(x_kick, y_kick, z_kick);
00433 //      PRL(kick_velocity);
00434       anomal_velocity = kick_velocity;
00435 // cerr << "Kick   : "<< v_kick <<" " << theta_kick <<" " << phi_kick<< endl;
00436 // cerr << "kick v : " << anomal_velocity << endl;
00437 
00438       velocity = sqrt(pow(v_kick, 2) + pow(velocity, 2)
00439                + 2*v_kick*velocity*sin(theta_kick)*cos(phi_kick));
00440       envelope_mass = 0;
00441 //      cerr << "return hit_companion;" <<hit_companion << flush << endl;
00442       return hit_companion;
00443     }
00444     else if(get_binary()->get_bin_type() == Disrupted ||
00445             get_binary()->get_bin_type() == Merged) {
00446 
00447       get_companion()->set_spec_type(Accreting, false);
00448 
00449       velocity = sqrt(pow(v_kick, 2) + pow(velocity, 2)
00450                + 2*v_kick*velocity*sin(theta_kick)*cos(phi_kick));
00451       envelope_mass = 0;
00452       return hit_companion;
00453     }
00454     else if (get_binary()->get_bin_type() != Merged &&
00455              get_binary()->get_bin_type() != Disrupted) {
00456 
00457       real a_init = get_binary()->get_semi();
00458       real e_init = get_binary()->get_eccentricity();
00459       real mtot_0 = get_binary()->get_total_mass();
00460       real msn_0 = get_total_mass();
00461       real m_psn = core_mass;
00462       real m_comp_0 = mtot_0 - msn_0;
00463       real m_comp = m_comp_0;
00464 
00465       real separation = random_separation(a_init, e_init);
00466       real a_new = post_sn_semi_major_axis(a_init, e_init, separation,
00467                                            msn_0, m_comp_0, m_psn, m_comp,
00468                                            v_kick, theta_kick, phi_kick);
00469       real e_new = post_sn_eccentricity(a_init, e_init, separation,
00470                                         msn_0, m_comp_0, m_psn, m_comp,
00471                                         v_kick, theta_kick, phi_kick);
00472       real v_cm  = post_sn_cm_velocity(a_init, e_init, separation,
00473                                        msn_0, m_comp_0, m_psn, m_comp,
00474                                        v_kick, theta_kick, phi_kick);
00475 
00476 //              System bound after kick?
00477       if (e_new>=0 && e_new<1.) {
00478         get_binary()->set_eccentricity(e_new);
00479         get_binary()->set_semi(a_new);
00480 
00481         get_binary()->set_velocity(v_cm);
00482         get_binary()->calculate_velocities();
00483             
00484 //              Does it hit the companion?
00485         real pericenter = a_new*(1-e_new);
00486         if (pericenter<=get_companion()->get_radius())
00487           hit_companion = TRUE;
00488       }
00489       else {
00490         spec_type[Runaway]=Runaway;
00491         
00492         get_binary()->set_eccentricity(1);
00493         get_companion()->set_spec_type(Runaway);
00494         get_binary()->set_bin_type(Disrupted);
00495         get_binary()->set_semi(0);
00496         real e2_init = e_init*e_init;
00497         real vr_mean_0 = sqrt(((cnsts.physics(G)*cnsts.parameters(solar_mass)
00498                        / cnsts.parameters(solar_radius))
00499                        * (msn_0+m_comp_0)/a_init)
00500                        * (1-e2_init)/pow(1+0.5*e2_init, 2));
00501         vr_mean_0 /= cnsts.physics(km_per_s);
00502         real mu_0 = get_total_mass()/mtot_0;
00503         real v_comp = mu_0*vr_mean_0;
00504 //      v_comp = velocity_at_infinity(v_comp, separation, m_comp, m_psn);
00505 
00506         real v_sn_0 = (1-mu_0)*vr_mean_0;
00507         real v_sn   = sqrt(v_sn_0*v_sn_0 + v_kick*v_kick
00508                      + 2*v_sn_0*v_kick*sin(theta_kick)*cos(phi_kick));
00509 //      v_sn = velocity_at_infinity(v_sn, separation, m_psn, m_comp);
00510 
00511 //              Now corect for binary CM velocity:
00512         real v_cm = get_binary()->get_velocity();
00513         v_comp = sqrt(pow(v_comp, 2) + pow(v_cm, 2)
00514                       + 2*v_comp*v_cm*cos(theta_kick));
00515         get_companion()->set_velocity(v_comp);
00516         v_sn = sqrt(pow(v_sn, 2) + pow(v_cm, 2)
00517                     + 2*v_sn*v_cm*cos(theta_kick));
00518         velocity = v_sn;
00519          }
00520       }
00521     envelope_mass = 0;
00522 
00523     return hit_companion;
00524 }
00525 
00526 // Reduce the mass of the donor when it's filling its Roche-lobe.
00527 // For a black_hole this is, of cource, not appropriate.
00528 star* black_hole::reduce_mass(const real mdot) {
00529 
00530       if (mdot>envelope_mass) 
00531          envelope_mass = 0;
00532       else 
00533          envelope_mass -= mdot;
00534       return this;
00535    }
00536 
00537 // Colide and merge just created neutron star with its companion.
00538 // Call is rare but could happen is high velocity kicks are included.
00539 void black_hole::direct_hit() {
00540 //      Binary and triple stuff....
00541 
00542       real theta = random_angle(0, cnsts.mathematics(two_pi));
00543       real v_bin = get_binary()->get_velocity();
00544       real ek_ns = get_total_mass()*velocity*velocity;
00545       real ek_comp = get_companion()->get_total_mass()
00546                    * pow(get_companion()->get_velocity(), 2);
00547       real v_merger = sqrt((ek_ns+ek_comp)/get_binary()->get_total_mass());
00548       real v_new = sqrt(pow(v_merger, 2) + pow(v_bin, 2)
00549                  + 2*v_merger*v_bin*cos(theta));
00550 
00551       get_binary()->set_semi(0);
00552       if (get_total_mass() >= get_companion()->get_total_mass())
00553          get_binary()->merge_elements(this, get_companion());
00554       else
00555          get_binary()->merge_elements(get_companion(), this);
00556 
00557       get_binary()->set_semi(0);
00558       get_binary()->set_velocity(v_new);
00559       get_binary()->get_primary()->set_velocity(v_new);
00560 
00561       get_binary()->dump("hit.data", false);
00562    }
00563 
00564 real black_hole::sudden_mass_loss() {
00565 
00566     real mass_lost = suddenly_lost_mass;
00567     suddenly_lost_mass = 0;
00568 
00569     return mass_lost;
00570 
00571    }
00572 
00573 
00574 real black_hole::gyration_radius_sq() {
00575 
00576   real a = 1;
00577   return a/(cnsts.physics(C)*pow(radius, 2));
00578 }
00579 
00580 // Angular momentum of homogeneous sphere.
00581 real black_hole::angular_momentum() {
00582   
00583   cerr << "black_hole::angular_momentum()"<<endl;
00584        
00585   real a = 1;   // Kerr black hole: maximum rotation
00586   real m = get_total_mass()*cnsts.parameters(solar_mass);
00587 
00588   return a*m;
00589         
00590 }
00591 
00592 

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