00001
00002
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
00013
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
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
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
00095 suddenly_lost_mass = 0;
00096 relative_age = 0;
00097
00098 bool hit_companion = super_nova();
00099 post_supernova_story();
00100
00101
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
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
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
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
00248
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
00270
00271 effective_radius = radius;
00272 }
00273
00274
00275
00276
00277
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
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
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
00308
00309
00310
00311
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
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
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
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
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 bool black_hole::super_nova() {
00403
00404 suddenly_lost_mass = envelope_mass;
00405
00406 bool hit_companion = FALSE;
00407
00408
00409 real impulse_kick =
00410 cnsts.parameters(kanonical_neutron_star_mass)/core_mass;
00411
00412
00413
00414
00415
00416 real v_kick = cnsts.super_nova_kick(no_velocity_kick);
00417
00418
00419
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
00425
00426 if (get_use_hdyn()) {
00427
00428
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
00434 anomal_velocity = kick_velocity;
00435
00436
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
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
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
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
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
00510
00511
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
00527
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
00538
00539 void black_hole::direct_hit() {
00540
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
00581 real black_hole::angular_momentum() {
00582
00583 cerr << "black_hole::angular_momentum()"<<endl;
00584
00585 real a = 1;
00586 real m = get_total_mass()*cnsts.parameters(solar_mass);
00587
00588 return a*m;
00589
00590 }
00591
00592