00001
00002
00003
00004 #include "stdfunc.h"
00005
00006 #ifndef TOOLBOX
00007
00008
00009
00010
00011
00012
00013 real tf2_energy_diss(const real eta, const stellar_type type) {
00014
00015
00016 real coeff2[] = {-0.397, 1.678, 1.277, -12.42, 9.446, -5.550};
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 real y = log10(eta);
00063 y = min(1.0, max(y, 0.0));
00064 real logT = ((((coeff2[5]*y + coeff2[4])*y + coeff2[3])*y
00065 + coeff2[2])*y + coeff2[1])*y + coeff2[0];
00066
00067
00068 return pow(10., logT);
00069 }
00070
00071
00072
00073
00074 real tf3_energy_diss(const real eta, const stellar_type type) {
00075
00076
00077 real coeff3[] = {-0.909, 1.574, 12.37, -57.40, 80.10, -46.43};
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 real y = log10(eta);
00124 y = min(1.0, max(y, 0.0));
00125 real logT = ((((coeff3[5]*y + coeff3[4])*y + coeff3[3])*y
00126 + coeff3[2])*y + coeff3[1])*y + coeff3[0];
00127
00128
00129 return pow(10., logT);
00130 }
00131
00132
00133 real lineair_interpolation(const real x,
00134 const real x1, const real x2,
00135 const real y1, const real y2) {
00136
00137 real a = (y2-y1)/(x2-x1);
00138 real b = y1 - a*x1;
00139
00140 real y = a*x + b;
00141 return y;
00142 }
00143
00144
00145
00146
00147
00148
00149 real post_sn_cm_velocity(const real a_init, const real e_init,
00150 const real separation,
00151 const real m1_0, const real m2_0,
00152 const real m1, const real m2,
00153 const real v_kick,
00154 const real theta, const real phi) {
00155
00156
00157 real v_orb = sqrt((cnsts.physics(G)*cnsts.parameters(solar_mass)/cnsts.parameters(solar_radius))*(m1_0+ m2_0)*(2/separation - 1/a_init));
00158
00159 real vr_k = cnsts.physics(km_per_s)*v_kick/v_orb;
00160
00161 real mu = m1_0*m2_0/(m1_0+m2_0);
00162 mu *= cnsts.parameters(solar_mass);
00163 real dm = (m1_0+m2_0) - (m1+m2);
00164 dm *= cnsts.parameters(solar_mass);
00165 real v_cm = v_orb/(cnsts.parameters(solar_mass)*(m1 + m2));
00166 v_cm *= sqrt(pow(mu*dm/(cnsts.parameters(solar_mass)*m1_0), 2) - 2*(mu*dm*m1/m1_0)
00167 * vr_k*sin(theta)*cos(phi) + pow(cnsts.parameters(solar_mass)*m1*vr_k, 2));
00168 v_cm /= cnsts.physics(km_per_s);
00169
00170
00171 return v_cm;
00172 }
00173
00174
00175 real post_sn_semi_major_axis(const real a_init, const real e_init,
00176 const real separation,
00177 const real m1_0, const real m2_0,
00178 const real m1, const real m2,
00179 const real v_kick,
00180 const real theta, const real phi) {
00181
00182
00183 real mu = (m1 + m2)/(m1_0 + m2_0);
00184 real v_orb = sqrt((cnsts.physics(G)*cnsts.parameters(solar_mass)/cnsts.parameters(solar_radius))*(m1_0+ m2_0)*(2/separation - 1/a_init));
00185 v_orb /= cnsts.physics(km_per_s);
00186 real vr_k = v_kick/v_orb;
00187 real vr2 = 1 + vr_k*vr_k + 2*vr_k*sin(theta)*cos(phi);
00188 real a_new = 1/(2/separation - (vr2/mu)*(2/separation - 1/a_init));
00189 real alpha = a_new/a_init;
00190
00191 real epsilon = (1/(mu*alpha))*(vr2 - vr_k*vr_k*pow(cos(theta), 2));
00192 real e_new = sqrt(1 - (1-e_init*e_init)*epsilon);
00193
00194
00195
00196
00197 return a_new;
00198 }
00199
00200 real post_sn_eccentricity(const real a_init, const real e_init,
00201 const real separation,
00202 const real m1_0, const real m2_0,
00203 const real m1, const real m2,
00204 const real v_kick,
00205 const real theta, const real phi) {
00206
00207 real mu = (m1 + m2)/(m1_0 + m2_0);
00208 real v_orb = sqrt((cnsts.physics(G)*cnsts.parameters(solar_mass)/cnsts.parameters(solar_radius))*(m1_0+ m2_0)*(2/separation - 1/a_init));
00209 v_orb /= cnsts.physics(km_per_s);
00210 real vr_k = v_kick/v_orb;
00211 real vr2 = 1 + vr_k*vr_k + 2*vr_k*sin(theta)*cos(phi);
00212 real a_new = 1/(2/separation - (vr2/mu)*(2/separation - 1/a_init));
00213 real alpha = a_new/a_init;
00214
00215 real epsilon = (1/(mu*alpha))*(vr2 - vr_k*vr_k*pow(cos(theta), 2));
00216 real e_new = sqrt(1 - (1-e_init*e_init)*epsilon);
00217
00218 return e_new;
00219 }
00220
00221 real kinetic_energy(const real mass, const real velocity) {
00222 real Mkm_s2 = cnsts.parameters(solar_mass)*cnsts.physics(km_per_s)*cnsts.physics(km_per_s);
00223 real k = 0.5*Mkm_s2*mass*velocity*velocity;
00224 return k;
00225 }
00226 real potential_energy(const real sep, const real m1, const real m2) {
00227
00228 real GM2_R = cnsts.physics(G)*cnsts.parameters(solar_mass)*cnsts.parameters(solar_mass)/cnsts.parameters(solar_radius);
00229 real u = GM2_R*m1*m2/sep;
00230 return -u;
00231 }
00232
00233 real velocity_at_infinity(const real vel,
00234 const real sep,
00235 const real m_prim,
00236 const real m_sec) {
00237
00238 real e_kin = kinetic_energy(m_prim+m_sec, vel);
00239 real e_pot = potential_energy(sep, m_prim, m_sec);
00240 real m_tot = cnsts.parameters(solar_mass)*(m_prim + m_sec);
00241 real velocity = 0;
00242 if (e_kin>abs(e_pot))
00243 velocity = sqrt((e_kin + e_pot)/m_tot);
00244
00245 return velocity/cnsts.physics(km_per_s);
00246 }
00247
00248 real random_angle(const real min, const real max) {
00249
00250 extern real randinter(real, real);
00251
00252 real rnd = randinter(min, max);
00253
00254
00255 return rnd;
00256 }
00257
00258 real random_eccentric_anomaly(const real ecc) {
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 real mean_anomaly = random_angle(0, cnsts.mathematics(two_pi));
00278
00279
00280
00281 real ecc_anomaly = mean_anomaly
00282 + cnsts.mathematics(two_pi)*(ecc*sin(mean_anomaly)
00283 + 0.5*ecc*ecc*sin(2*mean_anomaly));
00284
00285 real m0 = ecc_anomaly - ecc*sin(ecc_anomaly);
00286 real de0 = (mean_anomaly-m0)
00287 / (1 - ecc*cos(ecc_anomaly));
00288
00289 ecc_anomaly += de0;
00290 real m1, de1;
00291 do {
00292 m1 = ecc_anomaly - ecc*sin(ecc_anomaly);
00293
00294 de1 = (mean_anomaly-m1)
00295 / (1 - ecc*cos(ecc_anomaly));
00296
00297 ecc_anomaly += de1;
00298
00299 }
00300 while(de1>=0.001);
00301
00302
00303 return ecc_anomaly;
00304 }
00305
00306 real eccentric_anomaly(const real ecc, const real mean_anomaly) {
00307
00308
00309
00310
00311
00312
00313
00314
00315 real ecc_anomaly = mean_anomaly
00316 + cnsts.mathematics(two_pi)*(ecc*sin(mean_anomaly)
00317 + 0.5*ecc*ecc*sin(2*mean_anomaly));
00318
00319 real m0 = ecc_anomaly - ecc*sin(ecc_anomaly);
00320 real de0 = (mean_anomaly-m0)
00321 / (1 - ecc*cos(ecc_anomaly));
00322
00323 ecc_anomaly += de0;
00324 real m1, de1;
00325 do {
00326 m1 = ecc_anomaly - ecc*sin(ecc_anomaly);
00327
00328 de1 = (mean_anomaly-m1)
00329 / (1 - ecc*cos(ecc_anomaly));
00330
00331 ecc_anomaly += de1;
00332
00333 }
00334 while(de1>=0.001);
00335
00336
00337 return ecc_anomaly;
00338 }
00339
00340
00341 real random_separation(const real semi, const real ecc) {
00342
00343
00344 real ecc_anomaly = random_eccentric_anomaly(ecc);
00345
00346
00347 real separation = semi*(1-ecc*cos(ecc_anomaly));
00348
00349
00350 return separation;
00351 }
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 real maxwellian(const real velocity, const real v_disp) {
00378
00379
00380 real Mxwmax = 4/(sqrt(cnsts.mathematics(pi))*exp(1));
00381 real u2 = pow(velocity/v_disp, 2);
00382 real prob = (4./sqrt(cnsts.mathematics(pi))) * u2 / exp(u2);
00383 prob /= Mxwmax;
00384
00385 return prob;
00386 }
00387
00388 real random_maxwellian_velocity(const real v_disp) {
00389
00390 real rnd_gauss, v[3];
00391 real final_vel=0;
00392 real mean_vel = 0.;
00393 real v1d_disp = v_disp/sqrt(3.);
00394
00395 for (int i=0; i<3; i++) {
00396 rnd_gauss = gauss();
00397 v[i] = mean_vel + v1d_disp*rnd_gauss;
00398 final_vel += v[i]*v[i];
00399 }
00400
00401 return sqrt(final_vel);
00402 }
00403
00404 real paczynski_distribution(const real velocity, const real v_disp) {
00405
00406 real prob = (4./cnsts.mathematics(pi))/pow(1+pow(velocity/v_disp, 2.), 2.);
00407
00408
00409 prob /= (4./cnsts.mathematics(pi));
00410
00411 return prob;
00412 }
00413
00414
00415 real random_paczynski_velocity(const real v_disp) {
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426 real prob, velocity, dist_value;
00427 real max_distr = 4./cnsts.mathematics(pi);
00428 real v_max = 4;
00429 do {
00430 prob = max_distr*randinter(0., 1.);
00431 velocity = v_max*randinter(0., 1.);
00432 dist_value = max_distr/pow(1+pow(velocity, 2.), 2.);
00433 }
00434 while(prob>dist_value);
00435
00436 return velocity*v_disp;
00437 }
00438
00439 real cross_section(const real m_prim, const real m_sec,
00440 const real r_min, const real v_rel) {
00441
00442 real cgs_const = cnsts.physics(G)*cnsts.parameters(solar_mass)/(cnsts.parameters(solar_radius)*pow(cnsts.physics(km_per_s), 2));
00443 real gr_foc = cgs_const*(m_prim+m_sec)/(r_min*pow(v_rel, 2));
00444 real sigma = cnsts.mathematics(pi)*pow(r_min*cnsts.parameters(solar_radius), 2) * (1 + gr_foc);
00445 sigma /= pow(cnsts.parameters(solar_radius), 2);
00446
00447 return sigma;
00448 }
00449
00450 real eddington_limit(const real radius,
00451 const real dt,
00452 const real mu) {
00453 return cnsts.parameters(solar_radius)*radius*dt*mu*1.5e-08;
00454 }
00455
00456 real gf_velocity_distribution_extremum(const real m_prim, const real m_sec,
00457 const real r_min, const real v_disp) {
00458
00459 real abc_A = 3*cnsts.parameters(solar_radius)*r_min/pow(cnsts.physics(km_per_s)*v_disp, 2);
00460 real abc_B = 6*cnsts.physics(G)*cnsts.parameters(solar_mass)*(m_prim+m_sec)/pow(cnsts.physics(km_per_s)*v_disp, 2) - 4*cnsts.parameters(solar_radius)*r_min;
00461 real abc_C = -4*cnsts.physics(G)*cnsts.parameters(solar_mass)*(m_prim+m_sec);
00462 real discriminant = pow(abc_B, 2) - 4*abc_A*abc_C;
00463 real kappa1 = (-abc_B + sqrt(discriminant))/(2*abc_A);
00464 real kappa2 = (-abc_B - sqrt(discriminant))/(2*abc_A);
00465 real extremum1 = sqrt(abs(kappa1))/cnsts.physics(km_per_s);
00466
00467
00468
00469
00470 return extremum1;
00471 }
00472
00473
00474
00475
00476
00477 real gravitational_focussed_velocity(const real m_prim, const real m_sec,
00478 const real r_min, const real vel,
00479 const real v_disp) {
00480
00481 real konst = 4*sqrt(cnsts.mathematics(pi))*pow(3./(2*pow(v_disp*cnsts.physics(km_per_s), 2)), 3./2.);
00482 real GMm = cnsts.physics(G)*cnsts.parameters(solar_mass)*(m_prim+m_sec);
00483 real e_x = 1./exp((3./2.)*pow(vel/v_disp, 2));
00484 real velocity = vel*cnsts.physics(km_per_s);
00485 real s1 = pow(velocity, 3)*pow(cnsts.parameters(solar_radius)*r_min, 2);
00486 real s2 = 2*GMm*velocity*cnsts.parameters(solar_radius)*r_min;
00487
00488 real pvs = konst*e_x*(s1 + s2);
00489
00490 return pvs;
00491
00492 }
00493
00494 real random_focussed_maxwellian_velocity(const real m_prim, const real m_sec,
00495 const real r_min, const real v_disp,
00496 const real v_esc) {
00497
00498 real v_extremum = gf_velocity_distribution_extremum(m_prim, m_sec,
00499 r_min, v_disp);
00500 real max_prob = gravitational_focussed_velocity(m_prim, m_sec,
00501 r_min, v_extremum, v_disp);
00502
00503 real pprob, velocity, prob;
00504 do {
00505 pprob = randinter(0, 1.25);
00506 velocity = randinter(0, v_esc);
00507 prob = gravitational_focussed_velocity(m_prim, m_sec,
00508 r_min, velocity, v_disp)
00509 / max_prob;
00510 }
00511 while (prob<pprob);
00512
00513 return velocity;
00514
00515 }
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533 real gauss(const real velocity, const real v_disp) {
00534
00535 real u2 = pow(velocity/v_disp, 2);
00536 real prob = 1./exp(u2);
00537
00538 return prob;
00539 }
00540
00541 real gauss() {
00542
00543 extern real randinter(real, real);
00544
00545 static int iset = 0;
00546
00547
00548 real ret_val, r_1, r_2;
00549
00550
00551
00552
00553
00554 static real gset, r, v1, v2, fac;
00555
00556
00557
00558 if (iset == 0) {
00559 do {
00560 v1 = 2*randinter(0, 1) - 1.;
00561 v2 = 2*randinter(0, 1) - 1.;
00562
00563 r_1 = v1;
00564
00565 r_2 = v2;
00566 r = r_1 * r_1 + r_2 * r_2;
00567 }
00568 while(r >= 1.);
00569 fac = sqrt(-2*log(r)/r);
00570 gset = v1 * fac;
00571 ret_val = v2 * fac;
00572 iset = 1;
00573 } else {
00574 ret_val = gset;
00575 iset = 0;
00576 }
00577
00578 return ret_val;
00579 }
00580
00581 real turn_off_mass(const real time) {
00582
00583 real mass = 0.5*cnsts.parameters(maximum_main_sequence);
00584 real mdot = mass;
00585 real to_time = main_sequence_time(mass);
00586
00587 while(abs(time-to_time)>1.e-4) {
00588 mdot *= 0.5;
00589 if(to_time>time)
00590 mass += mdot;
00591 else
00592 mass -= mdot;
00593 to_time = main_sequence_time(mass);
00594
00595 if(mass>=cnsts.parameters(maximum_main_sequence)
00596 -cnsts.safety(minimum_mass_step) ||
00597 mass<=cnsts.parameters(minimum_main_sequence)
00598 -cnsts.safety(minimum_mass_step))
00599 to_time = time;
00600 }
00601
00602 return mass;
00603 }
00604
00605 real main_sequence_time(const real mass) {
00606
00607 real t_ms = (2550. + 667.*pow(mass,2.5)
00608 + pow(mass,4.5) )
00609 / (0.0327*pow(mass,1.5)
00610 + 0.346*pow(mass,4.5));
00611
00612 return t_ms;
00613 }
00614
00615 real zero_age_main_sequnece_radius(const real mass) {
00616
00617 real alpha, beta, gamma, delta, kappa, lambda;
00618
00619 real log_mass = log10(mass);
00620
00621 if (mass > 1.334) {
00622
00623 alpha = 0.1509 + 0.1709*log_mass;
00624 beta = 0.06656 - 0.4805*log_mass;
00625 gamma = 0.007395 + 0.5083*log_mass;
00626 delta = (0.7388*pow(mass, 1.679) - 1.968*pow(mass, 2.887))
00627 / (1.0 - 1.821*pow(mass, 2.337));
00628 }
00629 else {
00630
00631 alpha = 0.08353 + 0.0565*log_mass;
00632 beta = 0.01291 + 0.2226*log_mass;
00633 gamma = 0.1151 + 0.06267*log_mass;
00634 delta = pow(mass, 1.25) * (0.1148 + 0.8604*mass*mass)
00635 / (0.04651 + mass*mass);
00636 }
00637
00638 real radius = delta;
00639
00640 return radius;
00641 }
00642
00643
00644 real roche_radius(const real a, const real m1, const real m2) {
00645
00646 real q = m1/m2;
00647 real q1_3 = pow(q, cnsts.mathematics(one_third));
00648 real q2_3 = pow(q1_3, 2);
00649
00650 real Rl = a*0.49*q2_3/(0.6*q2_3 + log(1 + q1_3));
00651
00652 return Rl;
00653 }
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713 void polint(real xa[], real ya[], int n, real x, real *y, real *dy)
00714 {
00715 int i,m,ns=1;
00716 real den,dif,dift,ho,hp,w;
00717 real *c,*d;
00718 void free_vector(real *v, long nl, long nh);
00719 real *vector(long nl, long nh);
00720
00721 dif=fabs(x-xa[1]);
00722 c=vector(1,n);
00723 d=vector(1,n);
00724 for (i=1;i<=n;i++) {
00725 if ( (dift=fabs(x-xa[i])) < dif) {
00726 ns=i;
00727 dif=dift;
00728 }
00729 c[i]=ya[i];
00730 d[i]=ya[i];
00731 }
00732 *y=ya[ns--];
00733 for (m=1;m<n;m++) {
00734 for (i=1;i<=n-m;i++) {
00735 ho=xa[i]-x;
00736 hp=xa[i+m]-x;
00737 w=c[i+1]-d[i];
00738 if ( (den=ho-hp) == 0.0)
00739 cerr<<"Error in routine polin t";
00740 den=w/den;
00741 d[i]=hp*den;
00742 c[i]=ho*den;
00743 }
00744 *y += (*dy=(2*ns < (n-m) ? c[ns+1] : d[ns--]));
00745 }
00746 free_vector(d,1,n);
00747 free_vector(c,1,n);
00748 }
00749 #undef NRANSI
00750 #define NR_END 1
00751 #define FREE_ARG char*
00752
00753 void free_vector(real *v, long nl, long nh)
00754
00755 {
00756 free((FREE_ARG) (v+nl-NR_END));
00757 }
00758
00759 real *vector(long nl, long nh)
00760
00761 {
00762 real *v;
00763
00764 v=(real *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(real)));
00765 if (!v) cerr<<"allocation failure in vector()";
00766 return v-nl+NR_END;
00767 }
00768
00769 void fool(char * message) {
00770
00771 cerr << "Fool: You canot " << message << "!" << endl;
00772 }
00773
00774
00775
00776 real kelvin_helmholds_timescale(const real mass,
00777 const real radius,
00778 const real luminosity) {
00779 return 31.56*pow(mass,2.)/(radius*luminosity);
00780 }
00781
00782 real nucleair_evolution_timescale(const real mass,
00783 const real luminosity) {
00784
00785
00786
00787 real fused_mass = 0.1*mass;
00788
00789 return cnsts.parameters(energy_to_mass_in_internal_units)
00790 * fused_mass/luminosity;
00791
00792 }
00793
00794 real dynamic_timescale(const real mass,
00795 const real radius) {
00796
00797 return 5.08e-11*sqrt(pow(radius, 3.)/mass);
00798 }
00799
00800 #else
00801
00802 void main() {
00803
00804 real v_disp = 8;
00805
00806 for(int i=0; i< 1000; i++) {
00807
00808
00809
00810
00811 real velocity = random_focussed_maxwellian_velocity(39.3, 15.3,
00812 1., v_disp, 4*v_disp);
00813 cerr << " v= " << velocity << endl;
00814
00815 }
00816
00817 }
00818
00819 #endif