Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

neutron_star.C

Go to the documentation of this file.
00001 #define DEBUG false
00002 //
00003 // neutron_star.C
00004 //
00005 
00006 #include "neutron_star.h"
00007 #include "hyper_giant.h"
00008 #include "super_giant.h"
00009 #include "thorne_zytkow.h"
00010 #include "helium_giant.h"
00011 
00012 
00013 // ANSI C++ first creates the base class before the dreived classes are
00014 // created. If this is done in another order we are in deep shit.
00015 
00016 neutron_star::neutron_star(super_giant & g) : single_star(g) {
00017 
00018       delete &g;
00019 
00020       magnetic_field  = cnsts.parameters(pulsar_magnetic_field);
00021       // log Gauss
00022       rotation_period = cnsts.parameters(pulsar_pulse_period);
00023       // seconde
00024 
00025 
00026       suddenly_lost_mass     = 0;
00027       real m_tot             = get_total_mass();
00028       core_mass = birth_mass = neutron_star_mass(Super_Giant);
00029       envelope_mass          = m_tot - core_mass;
00030       relative_age           = 0;
00031 
00032 // (GN+SPZ May  4 1999) last update age is time of previous type change
00033       last_update_age = next_update_age;
00034 
00035       bool hit_companion = super_nova();
00036       post_supernova_story();
00037 
00038       refresh_memory();
00039       instantaneous_element();
00040       update();
00041 
00042       post_constructor();
00043 
00044       if (hit_companion)            // Kick may cause coalescence.
00045          direct_hit();
00046 
00047       if (is_binary_component()) {
00048         get_binary()->set_first_contact(false);
00049         get_companion()->set_spec_type(Accreting, false);
00050         get_binary()->dump("binev.data", false);
00051       }
00052       else {
00053         dump("binev.data", false);
00054       }
00055 }
00056 
00057 neutron_star::neutron_star(hyper_giant & w) : single_star(w) {
00058 
00059       delete &w;
00060 
00061       magnetic_field  = cnsts.parameters(pulsar_magnetic_field);
00062       // log Gauss
00063       rotation_period = cnsts.parameters(pulsar_pulse_period);
00064       // seconde
00065 
00066       suddenly_lost_mass     = 0;
00067       real m_tot             = get_total_mass();
00068       core_mass = birth_mass = neutron_star_mass(Super_Giant);
00069       envelope_mass          = m_tot - core_mass;
00070       relative_age           = 0;
00071 
00072 // (GN+SPZ May  4 1999) last update age is time of previous type change
00073       last_update_age = next_update_age;
00074 
00075       bool hit_companion = super_nova();
00076       post_supernova_story();
00077 
00078       refresh_memory();
00079       instantaneous_element();
00080       update();
00081 
00082       post_constructor();
00083 
00084       if (hit_companion) 
00085          direct_hit();
00086 
00087       post_constructor();
00088 
00089       if (is_binary_component()) {
00090         get_binary()->set_first_contact(false);
00091         dump("binev.data", false);
00092         get_companion()->set_spec_type(Accreting, false);
00093       }
00094       else {
00095         dump("binev.data", false);
00096       }
00097 }
00098 
00099 neutron_star::neutron_star(thorne_zytkow & t) : single_star(t) {
00100 
00101       delete &t;
00102 
00103       suddenly_lost_mass = 0;
00104 
00105 // (GN+SPZ May  4 1999) last update age is time of previous type change
00106       last_update_age = next_update_age;
00107 
00108       relative_age = 0;
00109       lose_envelope_decent();
00110 
00111       refresh_memory();
00112       instantaneous_element();
00113 
00114       post_constructor();
00115 
00116       if (is_binary_component()) 
00117         get_binary()->dump("binev.data", false);
00118       else 
00119         dump("binev.data", false);
00120 }
00121 
00122 neutron_star::neutron_star(helium_giant & h) : single_star(h) {
00123 
00124       delete &h;
00125 
00126 
00127 
00128       magnetic_field  = cnsts.parameters(pulsar_magnetic_field);
00129       // log Gauss
00130       rotation_period = cnsts.parameters(pulsar_pulse_period);
00131       // seconde
00132 
00133 
00134       suddenly_lost_mass     = 0;
00135       real m_tot             = get_total_mass();
00136       core_mass = birth_mass = neutron_star_mass(Helium_Star);
00137       envelope_mass          = m_tot - core_mass;
00138       relative_age           = 0;
00139 
00140 // (GN+SPZ May  4 1999) last update age is time of previous type change
00141       last_update_age = next_update_age;
00142 
00143       bool hit_companion = super_nova();
00144       post_supernova_story();
00145 
00146       refresh_memory();
00147       instantaneous_element();
00148       update();
00149 
00150       post_constructor();
00151 
00152       if (hit_companion)            // Kick may cause coalescence.
00153          direct_hit();
00154 
00155       if (is_binary_component()) {
00156         get_binary()->set_first_contact(false);
00157         get_companion()->set_spec_type(Accreting, false);
00158         get_binary()->dump("binev.data", false);
00159       }
00160       else {
00161         dump("binev.data", false);
00162       }
00163 }
00164 
00165 
00166 neutron_star::neutron_star(white_dwarf & w) : single_star(w) {
00167 
00168       delete &w;
00169       
00170       magnetic_field  = cnsts.parameters(pulsar_magnetic_field);
00171       // log Gauss
00172       rotation_period = cnsts.parameters(pulsar_pulse_period);
00173       // seconde
00174       
00175       suddenly_lost_mass = 0;
00176 
00177       real m_tot = get_total_mass();
00178       core_mass = birth_mass = max(0.0, m_tot - aic_binding_energy());
00179       envelope_mass = m_tot - core_mass;
00180       relative_age = 0;
00181 
00182 // (GN+SPZ May  4 1999) last update age is time of previous type change
00183       last_update_age = next_update_age;
00184 
00185       bool hit_companion = super_nova();
00186       post_supernova_story();
00187 
00188       refresh_memory();
00189       instantaneous_element();
00190       update();
00191       
00192       if (hit_companion) 
00193          direct_hit();
00194 
00195       post_constructor();
00196 
00197       if (is_binary_component()) {
00198         get_binary()->set_first_contact(false);
00199         get_companion()->set_spec_type(Accreting, false);
00200         get_binary()->dump("binev.data", false);
00201       }
00202       else {
00203         dump("binev.data", false);
00204       }
00205 }
00206 
00207 void neutron_star::instantaneous_element() {
00208   
00209   next_update_age = relative_age + cnsts.safety(maximum_timestep);
00210 
00211   core_radius = effective_radius = radius = neutron_star_radius();
00212   luminosity = spindown_luminosity();
00213 
00214   rotation_period = pulsar_spin_down(0);
00215 }
00216 
00217 void neutron_star::evolve_element(const real end_time) {
00218 
00219       real dt = end_time - current_time;
00220       current_time = end_time;
00221       relative_age += dt;
00222 
00223       core_radius = radius = neutron_star_radius();
00224       luminosity = spindown_luminosity();
00225 
00226       accrete_from_envelope(dt);
00227       rotation_period = pulsar_spin_down(dt);
00228 
00229       if (core_mass>cnsts.parameters(maximum_neutron_star_mass)) {
00230 
00231         if (is_binary_component()) 
00232           get_binary()->dump("binev.data", false);
00233         else
00234           dump("binev.data", false);
00235         
00236          star_transformation_story(Black_Hole);
00237          new black_hole(*this);
00238          return;
00239       }
00240 
00241       next_update_age = relative_age + cnsts.safety(maximum_timestep);
00242 
00243       update();
00244    }
00245 
00246 void neutron_star::update() {
00247 
00248       detect_spectral_features();
00249 // (GN+SPZ May  4 1999) last_update_age now used as time of last type change
00250 //  last_update_age = relative_age;
00251       effective_radius = radius;
00252 
00253 //      if(get_element_type() != previous.star_type) {
00254 //
00255 //      if (is_binary_component()) 
00256 //        get_binary()->dump("SeBa.data", true);
00257 //      else
00258 //        dump("SeBa.data", true);
00259 //      }
00260     }
00261 
00262 void neutron_star::accrete_from_envelope(const real dt) {
00263 
00264   if (DEBUG)
00265     cerr<<"neutron_star::accrete_from_envelope "<<dt<<endl;
00266   
00267   // real dm = NS_CORE_ACCRETION*accretion_limit(envelope_mass, dt);
00268   // Generally accretion onto neutron star core proceeds at 5% Eddington
00269   // For the moment this is 100% Eddington.
00270 
00271   real dm = accretion_limit(envelope_mass, dt);
00272 
00273   if (dm>0) {
00274     if (!propeller(dm, dt)) {
00275 
00276       magnetic_field  = magnetic_field_decay(dm, magnetic_field, dt);
00277       rotation_period = pulsar_spin_up(dm, dt);
00278       luminosity = accretion_luminosity(dm, dt);
00279 
00280       set_spec_type(Accreting);
00281     }
00282     else {
00283 
00284       rotation_period = pulsar_propeller_torque(dm, dt);
00285       real tau = 100;
00286       magnetic_field  = magnetic_field_decay(magnetic_field, dt/tau);
00287 
00288       set_spec_type(Accreting, false);
00289       dm = 0;
00290     }
00291   }
00292   else {
00293     real tau = 100;
00294     magnetic_field = magnetic_field_decay(magnetic_field, dt/tau);
00295 
00296     set_spec_type(Accreting, false);
00297   }
00298 
00299   core_mass += dm;
00300   envelope_mass = 0;
00301 }
00302 
00303 // Neutron star's binading energy. Energy fraction is lost during a
00304 // Accretion Induced colaescence of a white dwarf into a neutron star.
00305 // Since whole coalescence is not certain this function only used in
00306 // cases of allowing AIC to occur.
00307 // Typically one of those things that makes programming interesting.
00308 real neutron_star::aic_binding_energy() {
00309 
00310       real GM2_RC2 = 3*cnsts.physics(G)
00311                    * pow(cnsts.parameters(solar_mass)/cnsts.physics(C), 2)
00312                    / (5*cnsts.parameters(solar_radius));
00313       real binding_energy = (GM2_RC2*pow(core_mass,2)
00314                           / cnsts.parameters(kanonical_neutron_star_radius))
00315                           / cnsts.parameters(solar_mass);
00316 
00317       return binding_energy;
00318    }
00319 
00320 // One of the few routines that requires the random number generator.
00321 // random numbers:
00322 //      kick_velocity, 
00323 //      theta (kick-angel in orbital plane),
00324 //      phi   (kick-angel perpendicular to orbital plane).
00325 // separation is determined by solving Keplers equation for the 
00326 // Eccentric anomaly taking the mean anomaly randomly.
00327 //
00328 // Return value is boolian whather or not the remnant colescence 
00329 // with its companion.
00330 bool neutron_star::super_nova() {
00331 
00332      suddenly_lost_mass = envelope_mass;
00333 
00334      bool hit_companion = FALSE;
00335       
00336      real v_kick     = cnsts.super_nova_kick(); //random_kick();
00337      real theta_kick = acos(1-2*random_angle(0, 1));
00338      real phi_kick   = random_angle(0, 2*PI);
00339 
00340      cerr << "Supernova kick v = " << v_kick << " [km/s]" << endl;
00341       
00342      if (get_use_hdyn()) {
00343 
00344         real x_kick = v_kick*sin(theta_kick)*cos(phi_kick);
00345         real y_kick = v_kick*sin(theta_kick)*sin(phi_kick);
00346         real z_kick = v_kick*cos(theta_kick);
00347         vector kick_velocity(x_kick, y_kick, z_kick);
00348         anomal_velocity = kick_velocity;
00349 
00350         // This is correct if velocity is along the z-axis.
00351         velocity = sqrt(pow(v_kick, 2) + pow(velocity, 2)
00352                  + 2*v_kick*velocity*sin(theta_kick)*cos(phi_kick));
00353 
00354         envelope_mass = 0;
00355         return hit_companion;
00356       }
00357       else {
00358 
00359         // Supernova is performed by the binary evolution
00360 
00361         if(get_binary()->get_bin_type() == Disrupted ||
00362            get_binary()->get_bin_type() == Merged) {
00363 
00364           get_companion()->set_spec_type(Accreting, false);
00365 
00366           velocity = sqrt(pow(v_kick, 2) + pow(velocity, 2)
00367                    + 2*v_kick*velocity*sin(theta_kick)*cos(phi_kick));
00368 
00369           envelope_mass = 0;
00370           return hit_companion;
00371         }
00372         else if (get_binary()->get_bin_type() != Merged &&
00373                  get_binary()->get_bin_type() != Disrupted) {
00374 
00375           real a_init = get_binary()->get_semi();
00376           real e_init = get_binary()->get_eccentricity();
00377           real mtot_0 = get_binary()->get_total_mass();
00378           real msn_0 = get_total_mass();
00379           real m_psn = core_mass;
00380           real m_comp_0 = mtot_0 - msn_0;
00381           real m_comp = m_comp_0;
00382 
00383           real separation = random_separation(a_init, e_init);
00384           real a_new = post_sn_semi_major_axis(a_init, e_init, separation,
00385                                                msn_0, m_comp_0, m_psn, m_comp,
00386                                                v_kick, theta_kick, phi_kick);
00387           real e_new = post_sn_eccentricity(a_init, e_init, separation,
00388                                             msn_0, m_comp_0, m_psn, m_comp,
00389                                             v_kick, theta_kick, phi_kick); 
00390           real v_cm  = post_sn_cm_velocity(a_init, e_init, separation,
00391                                            msn_0, m_comp_0, m_psn, m_comp,
00392                                            v_kick, theta_kick, phi_kick);
00393 
00394           //              System bound after kick?
00395           if (e_new>=0 && e_new<1.) {
00396             get_binary()->set_eccentricity(e_new);
00397             get_binary()->set_semi(a_new);
00398 
00399             get_binary()->set_velocity(v_cm);
00400             get_binary()->calculate_velocities();
00401 
00402             //              Does it hit the companion?
00403             real pericenter = a_new*(1-e_new);
00404 
00405             if (pericenter <= get_companion()->get_radius())
00406               hit_companion = TRUE;
00407             
00408           }
00409           else {
00410             set_spec_type(Runaway);
00411 
00412             get_binary()->set_eccentricity(1);
00413             get_companion()->set_spec_type(Runaway);
00414             get_binary()->set_bin_type(Disrupted);
00415             get_binary()->set_semi(0);
00416 
00417             real e2_init = e_init*e_init;
00418             real vr_mean_0 = sqrt(((cnsts.physics(G)
00419                            *        cnsts.parameters(solar_mass)
00420                            /        cnsts.parameters(solar_radius))
00421                            *        (msn_0+m_comp_0)/a_init)
00422                            *        (1-e2_init)/pow(1+0.5*e2_init, 2));
00423             vr_mean_0      /= cnsts.physics(km_per_s);
00424             
00425             real mu_0 = get_total_mass()/mtot_0;
00426             real v_comp = mu_0*vr_mean_0;
00427 
00428             //              velocity at infinity.
00429             real v_sn_0 = (1-mu_0)*vr_mean_0;
00430             real v_sn   = sqrt(v_sn_0*v_sn_0 + v_kick*v_kick
00431                         + 2*v_sn_0*v_kick*sin(theta_kick)*cos(phi_kick));
00432 
00433             //              binary CoM velocity:
00434             real v_cm = get_binary()->get_velocity();
00435             v_comp = sqrt(pow(v_comp, 2) + pow(v_cm, 2)
00436                    + 2*v_comp*v_cm*cos(theta_kick));
00437             get_companion()->set_velocity(v_comp);
00438             
00439             v_sn = sqrt(pow(v_sn, 2) + pow(v_cm, 2)
00440                  + 2*v_sn*v_cm*cos(theta_kick));
00441             velocity = v_sn;
00442          }
00443       }
00444       envelope_mass = 0;
00445 
00446       }
00447      return hit_companion;
00448 }
00449 
00450 
00451 star* neutron_star::subtrac_mass_from_donor(const real dt, real& mdot) {
00452 
00453       mdot = mass_ratio_mdot_limit(accretion_limit(envelope_mass, dt));
00454 
00455       //                The disc may lose mass.
00456       envelope_mass -= mdot;
00457 
00458       return this;
00459 }
00460 
00461 real neutron_star::add_mass_to_accretor(const real mdot) {
00462 
00463       envelope_mass += mdot;
00464       relative_mass = max(relative_mass, get_total_mass());
00465       
00466       return mdot;
00467 }
00468 
00469 // Accrete on neutron star.
00470 // Eddington limited. The accreted mass first
00471 // enters a stallar envelope (disc) and is finally accreted on
00472 // the compact object.
00473 // So no magnetic field decay here.
00474 real neutron_star::add_mass_to_accretor(real mdot, const real dt) {
00475 
00476      if (DEBUG) cerr<<"neutron_star::add_mass_to_accretor "<<dt<<endl;
00477 
00478      mdot = accretion_limit(mdot, dt);
00479      envelope_mass += mdot;
00480      relative_mass = max(relative_mass, get_total_mass());
00481 
00482      return mdot;
00483 }
00484 
00485 // Limit the accretion onto the nuetron star by the Eddingtopn limit.
00486 real neutron_star::accretion_limit(const real mdot, const real dt) {
00487 
00488      real eddington = eddington_limit(radius, dt); 
00489 
00490    if (cnsts.parameters(hyper_critical))
00491       return min(mdot, (1.e+8)*eddington); 
00492 
00493    return min(mdot, eddington);
00494 
00495 }
00496 
00497 #if 0 // Old stuff
00498 real neutron_star::add_mass_to_accretor(const real mdot) {
00499 
00500       relative_mass = max(relative_mass, get_total_mass() + mdot);
00501       envelope_mass += mdot;
00502 
00503       return mdot;
00504    }
00505 
00506 // Accrete ont neutron star.
00507 // Neutron star accretes with Eddington limit. The accreted mass first
00508 // enters a starage envelope (disc) and is finally accreted onte 
00509 // the compact object.
00510 real neutron_star::add_mass_to_accretor(real mdot, const real dt) {
00511 
00512       mdot = accretion_limit(mdot, dt);
00513       relative_mass = max(relative_mass, get_total_mass() + mdot);
00514       envelope_mass += mdot;
00515 
00516       return mdot;
00517    }
00518 
00519 // Limit the accretion onto the nuetron star by the Eddingtopn limit.
00520 real neutron_star::accretion_limit(const real mdot, const real dt) {
00521 
00522      real eddington = eddington_limit(radius, dt); 
00523 //      real eddington = 1.5e-08*cnsts.parameters(solar_radius)*radius*dt;
00524 
00525       return min(mdot, eddington);
00526    }
00527 #endif // End old stuff
00528 
00529 star* neutron_star::merge_elements(star* str) {
00530 
00531       envelope_mass = 0;
00532       real merger_core = str->get_core_mass();
00533 
00534       add_mass_to_accretor(str->get_envelope_mass());
00535       relative_mass = max(relative_mass, get_total_mass() + merger_core);
00536       core_mass += merger_core;
00537 
00538       set_spec_type(Merger);
00539       instantaneous_element();
00540 
00541       return this;
00542 
00543    }
00544 
00545 star* neutron_star::reduce_mass(const real mdot) {
00546 
00547       if (mdot>envelope_mass) {
00548         real dm = mdot -envelope_mass;
00549         envelope_mass = 0;
00550         core_mass -= dm;
00551       }
00552       else envelope_mass -= mdot;
00553       
00554       return this;
00555 }
00556 
00557 void neutron_star::direct_hit() {
00558 
00559       real theta = random_angle(0, 2*PI);
00560       real v_bin = get_binary()->get_velocity();
00561       real ek_ns = get_total_mass()*velocity*velocity;
00562       real ek_comp = get_companion()->get_total_mass()
00563                    * pow(get_companion()->get_velocity(), 2);
00564       real v_merger = sqrt((ek_ns+ek_comp)/get_binary()->get_total_mass());
00565       real v_new = sqrt(pow(v_merger, 2) + pow(v_bin, 2)
00566                  + 2*v_merger*v_bin*cos(theta));
00567 
00568       get_binary()->set_semi(0);
00569       if (get_total_mass() >= get_companion()->get_total_mass())  
00570          get_binary()->merge_elements(this, get_companion()); 
00571       else 
00572          get_binary()->merge_elements(get_companion(), this); 
00573 
00574       get_binary()->set_bin_type(Merged);
00575       get_binary()->set_semi(0);
00576       get_binary()->set_velocity(v_new);
00577       get_binary()->get_primary()->set_velocity(v_new);
00578 
00579       get_binary()->dump("hit.data", false);
00580    }
00581 
00582 real neutron_star::sudden_mass_loss() {
00583 
00584     real mass_lost = suddenly_lost_mass;
00585     suddenly_lost_mass = 0;
00586 
00587     return mass_lost;
00588 
00589    }
00590 
00591 
00592 /*----------------------------------------------------------------------
00593  * Relation concerning the radio pulsar's evolution
00594  *----------------------------------------------------------------------
00595  */
00596 //      See Timmes, Woosley, Weaver, 1997, ApJ 457, 834
00597 //      Bimodal distribution for supernova type II progenitors and
00598 //      a single Gaussian for type I's
00599 //      For the moment a random function determines the mass of the remnant.
00600 //      If the mass appears to be above 2.0 Msun, evolve element
00601 //      transformes it into a black hole.
00602 //      Note that a kick is already applied in these cases.
00603 //      Which might as well be true: see Sigurdsson & Brandt (~1995).
00604 real neutron_star::neutron_star_mass(stellar_type stp) {
00605 
00606   real m = get_total_mass();
00607   if (stp==Helium_Star || stp==Hyper_Giant)
00608         m = 10 + get_total_mass();
00609   else
00610       m = relative_mass;
00611 
00612     real a, b, c, d, e;
00613     a =  2.25928E+00;
00614     b = -2.68264E-01;
00615     c =  2.28206E-02;
00616     d = -7.06583E-04;
00617     e =  7.48965E-06;
00618     real mass = a + m*(b + m*(c + m*(d + m*e)));
00619 
00620   mass = min(mass, cnsts.parameters(maximum_neutron_star_mass));
00621 
00622   return min(mass, get_total_mass());
00623 }
00624 
00625 //Assuming a Newtonian Polytrope with n= 3/2
00626 real neutron_star::neutron_star_radius() {
00627 
00628      return 15.12 * (cnsts.physics(kilometer)/cnsts.parameters(solar_radius))
00629                   / pow(core_mass, cnsts.mathematics(one_third));   // [rsun]
00630 }
00631 
00632 //Is this neutron star spinning so fast that it cannot accrete any matter?
00633 bool neutron_star::propeller(const real mdot, const real dt) {
00634      if (DEBUG)
00635        cerr<<"neutron_star::propeller"<<endl;
00636 
00637      real propellor = TRUE;
00638      real eddington = eddington_limit(radius, dt); 
00639 
00640      //Take the propeller effect into account, by allowing accretion
00641      //only to occur if mdot>propeller_limit
00642      if (is_binary_component() && eddington>0 && mdot>0 && dt>0) {
00643          real f = 1;
00644 
00645          real v_wind = get_companion()->wind_velocity();
00646          real v_orb  = velocity + get_companion()->get_velocity();
00647 //       real v2_rel  = sqrt(0.5 * (pow(v_wind, 2) + pow(v_orb, 2)));
00648          real v2_rel  = sqrt(pow(v_wind, 2) + pow(v_orb, 2));
00649          real propeller_limit = 2.06e-8*f
00650                               * pow(pow(10., magnetic_moment()-30), 2)
00651             / (v2_rel*pow(rotation_period, 4));               // [Msun/Myr]
00652 
00653          // no accterion, neutron star spins too rapidly.
00654          if (mdot>propeller_limit*dt)
00655                       propellor=FALSE;
00656      }
00657 
00658      if (DEBUG)
00659        cerr<<propellor<<endl;
00660 
00661     return propellor;
00662 }
00663 
00664 real neutron_star::moment_of_inertia() {
00665      if (DEBUG)
00666        cerr<<"neutron_star::moment_of_inertia = "<<endl;
00667 
00668      real MR2 = cnsts.parameters(solar_mass)
00669               * pow(cnsts.parameters(solar_radius), 2);
00670      real inertia = MR2*gyration_radius_sq()*core_mass*pow(radius, 2);
00671 
00672      if (DEBUG)
00673        cerr << inertia << endl;
00674 
00675   return inertia;
00676 }
00677 
00678 real neutron_star::period_derivative() {
00679     if (DEBUG)
00680       cerr<<"neutron_star::period_derivative"<<endl;
00681 
00682   real pi2R6_3c3 = cnsts.mathematics(one_third)*pow(cnsts.mathematics(pi), 2)
00683                  * pow( pow(cnsts.parameters(solar_radius), 2)
00684                  /          cnsts.physics(C), 3);
00685 
00686   real Bfield = pow(10., magnetic_field);
00687   real inertia = moment_of_inertia();
00688 
00689   real Pdot = 8*pi2R6_3c3*pow(radius, 6)*pow(Bfield, 2)
00690                 / (inertia*rotation_period);
00691 
00692 
00693     if (DEBUG)
00694       cerr << Pdot << endl;
00695 
00696   return Pdot;
00697 }
00698 
00699 real neutron_star::spindown_luminosity() {
00700      if (DEBUG)
00701        cerr<<"neutron_star::spindown_luminosity"<<endl;
00702 
00703      real L400 = 1;         // Luminosity at 400 Mhz.
00704      if (rotation_period>0) {
00705        real Pdot = period_derivative();
00706 
00707        real argument = Pdot/pow(rotation_period, 3);
00708 
00709        if(argument>0)
00710          L400 = pow(10., 6.63 + ONE_THIRD*log10(argument));
00711 
00712      }
00713      
00714      if (DEBUG)
00715        cerr<<L400<<endl;
00716 
00717      return L400;
00718 }
00719 
00720 real neutron_star::accretion_luminosity(const real dm,
00721                                         const real dt) {
00722     if (DEBUG)
00723       cerr<<"neutron_star::accretion_luminosity"<<endl;
00724 
00725     real L = spindown_luminosity();
00726 
00727     if (dm>0 &&  dt>0) {
00728       real dmdt = dm/dt;
00729       real GM2_RMyr = cnsts.physics(G)*pow(cnsts.parameters(solar_mass), 2)
00730                     / (cnsts.parameters(solar_radius)*cnsts.physics(Myear));
00731       L = GM2_RMyr*core_mass*dmdt/radius;
00732       L /= cnsts.parameters(solar_luminosity);
00733     }
00734     
00735     if (DEBUG)
00736       cerr<<L<<endl;
00737 
00738     return L;
00739 }
00740 
00741 real neutron_star::fastness_parameter(const real dmdt) {
00742     if (DEBUG)
00743       cerr<<"neutron_star::fastness_parameter"<<endl;
00744 
00745     real mu30 = pow(10., magnetic_moment()-30);
00746     real omega_s = 1.19*pow(mu30, 6./7.)
00747                  / (rotation_period*pow(dmdt, 3./7.)*pow(core_mass, 5./7.));
00748 
00749     if (DEBUG)
00750       cerr<< min(1-0.01, max(0.1, omega_s))<<endl;
00751 
00752     return min(1-0.01, max(0.1, omega_s));
00753 }
00754 
00755 real neutron_star::dimension_less_accretion_torque(const real dmdt) {
00756     if (DEBUG)
00757       cerr<<"neutron_star::dimension_less_accretion_torque"<<endl;
00758     
00759     real omega_s = fastness_parameter(dmdt);
00760     real n_omega = ((7./6.) - (4./3.)*omega_s + (1./9)*pow(omega_s, 2))
00761                  / (1-omega_s);
00762     
00763     if (DEBUG)
00764       cerr<<n_omega<<endl;
00765     
00766     return n_omega;
00767 }
00768 
00769 
00770 real neutron_star::pulsar_propeller_torque(const real dm,
00771                                            const real dt) {
00772      if (DEBUG)
00773        cerr<<"neutron_star::pulsar_propeller_torque"<<endl;
00774 
00775 //Pulsar torque due to drag should be taken into account.
00776 // the prescription below is for accreting pulsars, not propellering ones.
00777     
00778     real dmEdd = 1;
00779     real dmdt=1;
00780     if (dm>0 &&  dt>0) {
00781       dmdt = dm/dt;
00782       real Eddington = eddington_limit(radius, 1.0); 
00783       //real Eddington = 1.5e-08*cnsts.parameters(solar_radius)*radius; // [Msun/Myr]
00784       dmEdd = dmdt/Eddington;
00785     }
00786     
00787     real n_omega = dimension_less_accretion_torque(dmdt);
00788     real mu30 = pow(10., magnetic_moment()-30);
00789 
00790     real Pdot = -7.2 * n_omega * pow(mu30, 2./7.)
00791               * pow(dmEdd, 6./7.) * pow(rotation_period, 2); // [s/Myr]
00792     Pdot = max(0., Pdot);
00793 
00794     real delta_P = rotation_period + Pdot*dt;
00795     
00796     if (DEBUG)
00797       cerr<<delta_P<<endl;
00798 
00799     return delta_P;
00800 }
00801 
00802 real neutron_star::magnetic_moment() {
00803   
00804      real r3 = pow(radius*cnsts.parameters(solar_radius), 3);
00805                // log r^3 in [cm]
00806 
00807      return magnetic_field + log10(r3);
00808 }
00809 
00810 // Spontanious magnetic field decay.
00811 // the constant for field decay is tau=100 Myr.
00812 // The parameter dt_tau is actually dt/tau. Taken as a single parameter
00813 // to make function overloading workable.
00814 real neutron_star::magnetic_field_decay(const real log_B,
00815                                         const real dt_tau=0) {
00816   
00817      real B0 = pow(10., log_B);
00818      real B1 = max(1.,  B0 / exp(dt_tau));
00819 
00820      return log10(B1);
00821 }
00822 
00823 
00824 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00825 // local neutron star functions.
00826 // Currently only for an accretion rate of 10^-9 Msun/yr.
00827 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00828 real neutron_star::magnetic_field_decay(const real delta_m,
00829                                         const real log_B,
00830                                         const real dt=0) {
00831      real dmEdd = 1.0;
00832      if (delta_m>0 &&  dt>0) {
00833        real dmdt = delta_m/dt;
00834        real Eddington = eddington_limit(radius, 1.0); 
00835 
00836        dmEdd = dmdt/Eddington;
00837      }
00838      
00839      real B1 = magnetic_field_strength(core_mass, dmEdd);
00840      real B2 = magnetic_field_strength(core_mass+delta_m, dmEdd);
00841      real delta_B = min(0.0, B2-B1);
00842 
00843      return log_B + delta_B;
00844 }
00845 
00846 //The lineair interpolation is from :
00847 // Konar, S., 1997, PhD thesis, Indian Institute of Science,
00848 // Bangalorem India.
00849 // The lineair interpolated curve presented is for Mdor = 10^-9 Msun/yr.
00850 // For lower mass loss rates a linair shift is applied of
00851 // log dM = 0.5 and log dB = 0.3 per order of magnitude decrease
00852 // in accretion rate.
00853 real neutron_star::magnetic_field_strength(const real ns_mass,
00854                                            const real dmEdd = 1) {
00855 
00856       real delta_BBo = -0.2 * log10(dmEdd);
00857       real log_dm    = log10(ns_mass - birth_mass + 1.0e-10);
00858       log_dm        -= max(0.0, -0.5*(1+log10(dmEdd)));
00859 
00860       real log_dm_min  = -8.0;
00861       real log_dm_max  = -2;
00862       real log_BBo_min = -5.0;
00863       real log_BBo_max =  0.0;
00864 
00865       if (log_dm>-3)
00866                 return max(0.0, log_BBo_min + delta_BBo);
00867       if (log_dm<-7.5)
00868                 return log_BBo_max;
00869 
00870       if(log_dm>=-3.5) {
00871           log_dm_min  = -3.5;
00872           log_dm_max  = -3.0;
00873           log_BBo_min = -4.5;
00874           log_BBo_max = -4.9;
00875       }else if(log_dm>=-4.0) {
00876           log_dm_min  = -4.0;
00877           log_dm_max  = -3.5;
00878           log_BBo_min = -3.1;
00879           log_BBo_max = -4.5;
00880       }else if(log_dm>=-4.5) {
00881           log_dm_min  = -4.5;
00882           log_dm_max  = -4.0;
00883           log_BBo_min = -2.4;
00884           log_BBo_max = -3.1;
00885       }else if(log_dm>=-5.0) {
00886           log_dm_min  = -5.0;
00887           log_dm_max  = -4.5;
00888           log_BBo_min = -2.0;
00889           log_BBo_max = -2.4;
00890       }else if(log_dm>=-5.5) {
00891           log_dm_min  = -5.5;
00892           log_dm_max  = -5.0;
00893           log_BBo_min = -1.5;
00894           log_BBo_max = -2.0;
00895       }else if(log_dm>=-6.0) {
00896           log_dm_min  = -6.0;
00897           log_dm_max  = -5.5;
00898           log_BBo_min = -1.1;
00899           log_BBo_max = -1.5;
00900       }else if(log_dm>=-6.5) {
00901           log_dm_min  = -6.5;
00902           log_dm_max  = -6.0;
00903           log_BBo_min = -0.7;
00904           log_BBo_max = -1.1;
00905       }else if(log_dm>=-7.0) {
00906           log_dm_min  = -7.0;
00907           log_dm_max  = -6.5;
00908           log_BBo_min = -0.4;
00909           log_BBo_max = -0.7;
00910       }else if(log_dm>=-7.5) {
00911           log_dm_min  = -7.5;
00912           log_dm_max  = -7.0;
00913           log_BBo_min =  0.0;
00914           log_BBo_max = -0.4;
00915 }
00916 
00917 
00918       real log_B = lineair_interpolation(log_dm, log_dm_min, log_dm_max,
00919                                                log_BBo_min, log_BBo_max);
00920       log_B += delta_BBo;
00921 
00922       return min(0.0, log_B);
00923 }
00924 
00925 real neutron_star::pulsar_spin_up(const real dm, const real dt) {
00926 
00927      if (!is_binary_component())
00928        return rotation_period;
00929 
00930      real dmEdd = 1.0;
00931      if (dm>0 &&  dt>0) {
00932        real dmdt = dm/dt;
00933        real Eddington = eddington_limit(radius, 1.0); 
00934        dmEdd = dmdt/Eddington;
00935      }
00936      
00937      real B = pow(10., magnetic_field);
00938      real P_eq = 0.0019*pow(B/1.e+9, 6./7.)
00939                / (pow(core_mass/1.4, 5./7.)*pow(dmEdd, 3./7.));  // seconds
00940 
00941      return min(rotation_period, P_eq);
00942 }
00943 
00944 real neutron_star::pulsar_spin_down(const real dt) {
00945    if (DEBUG)
00946      cerr << "enter pulsar_spin_down( dt="<<dt<<")"<<endl;
00947 
00948    real B = pow(10., magnetic_field);
00949    real P0 = rotation_period;
00950 
00951    real Pdot = pow(B/3.2e+19, 2)/P0;
00952    real delta_P = Pdot * dt * cnsts.physics(Myear);
00953 
00954    return rotation_period + delta_P;
00955 }
00956 
00957 bool neutron_star::dead_pulsar() {
00958 
00959    bool dead = FALSE;
00960 
00961    real B = pow(10., magnetic_field);
00962    real Pdeath = sqrt(B/0.17e+12);
00963 
00964    if (rotation_period >=Pdeath)
00965           dead = TRUE;
00966 
00967    return dead;
00968 }
00969 
00970 real neutron_star::gyration_radius_sq() {
00971 
00972   // Gunn & Ostriker 1969, Nat. 221, 454
00973   // Momentum of inertia of 12km neutron star = 10^45 gr cm^2
00974   // this results in:
00975   
00976   return 0.25; 
00977   
00978 }
00979 
00980 stellar_type neutron_star::get_element_type() {
00981 
00982   // (SPZ+GN:  1 Aug 2000)
00983   // Currently not stable due to SeBa.data which would produce too much output.
00984   // Fix: implement next_update_age in neutron stars.C
00985 #if 0
00986   if (spec_type[Accreting])
00987     return Xray_Pulsar;
00988   else if (!dead_pulsar())
00989     return Radio_Pulsar;
00990   else
00991     return Neutron_Star;
00992 #endif
00993 
00994     return Neutron_Star;
00995 
00996 }
00997 
00998 
00999 
01000 

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