00001
00002
00003
00004
00005
00006
00007 #include "stdinc.h"
00008
00009 #define Grav 6.673e-8
00010 #define Msun 1.989e33
00011 #define AU 1.486e13
00012 #define Rsun 6.960e10
00013
00014 #define Kms 1e5
00015 #define SECONDS_IN_YEAR 3.16e7
00016 #define CM_IN_PC 3.086e18
00017
00018
00019
00020
00021
00022 #define N_MASS 48
00023 #define M_MIN 0.0 // M_MIN and M_MAX determine limits on mass for binning
00024 #define M_MAX 2.4 // purposes only. Actual limits are m_lower, m_upper.
00025
00026 #define N_HE 30
00027 #define MIN_HE 0.24 // MIN_HE and MAX_HE determine limits on mass for
00028 #define MAX_HE 0.39 // binning purposes only.
00029
00030 #define N_HEMASS 25
00031 #define M_HEMIN 0.0 // M_HEMIN and M_HEMAX determine limits on helium mass
00032 #define M_HEMAX 1.0 // for binning purposes only.
00033
00034 static real m_lower = 0.1;
00035 static real m_upper = 0.8;
00036 static real exponent = 1.35;
00037 static real m_unit;
00038
00039
00040
00041 #define N_INT 9
00042 static real m_int[N_INT] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.75, 0.8};
00043 static real r_int[N_INT] = {0.1, 0.2, 0.3, 0.4, 0.51, 0.63, 0.75, 1.09, 1.87};
00044 static real y_int[N_INT] = {0.240, 0.240, 0.243, 0.248, 0.254,
00045 0.273, 0.313, 0.347, 0.385};
00046
00047 static int n_scatt;
00048 static real sigma_1[N_MASS][N_HE];
00049 static real sigma_2[N_MASS][N_HEMASS];
00050 static real sigma_err_sq_1[N_MASS][N_HE];
00051 static real sigma_err_sq_2[N_MASS][N_HEMASS];
00052
00053
00054
00055 local int get_index(real m)
00056 {
00057 for (int i = 0; i < N_INT; i++) if (m_int[i] > m) return i-1;
00058 return N_INT - 1;
00059 }
00060
00061 local real get_quantity(real m, real* q)
00062 {
00063 int i = get_index(m);
00064
00065 if (i < 0)
00066 return q[0];
00067 else if (i >= N_INT-1)
00068 return q[N_INT-1];
00069
00070 return q[i] + (m - m_int[i]) * (q[i+1] - q[i]) / (m_int[i+1] - m_int[i]);
00071 }
00072
00073 local real radius(real m)
00074 {
00075 return get_quantity(m, r_int);
00076 }
00077
00078
00079 local real helium(real m)
00080 {
00081 return get_quantity(m, y_int);
00082 }
00083
00084
00085
00086
00087 local real get_mass(real ml, real mu, real x)
00088 {
00089 real r = randinter(0,1);
00090
00091 if (x == -1)
00092 return ml * exp( r*log(mu/ml) );
00093 else
00094 return ml * pow( 1 + r * (pow(mu/ml, 1+x) - 1), 1.0/(1+x));
00095 }
00096
00097
00098
00099
00100
00101 local void initialize_stats()
00102 {
00103 n_scatt = 0;
00104 for (int i = 0; i < N_MASS; i++) {
00105 for (int j = 0; j < N_HE; j++) sigma_1[i][j] = sigma_err_sq_1[i][j] = 0;
00106 for (j = 0; j < N_HEMASS; j++) sigma_2[i][j] = sigma_err_sq_2[i][j] = 0;
00107 }
00108 }
00109
00110 local void update_sigma2(real m1, real m2, real r1, real r2, real v_inf)
00111 {
00112 n_scatt++;
00113
00114 real mmerge = m1 + m2;
00115 real rmin = r1 + r2;
00116 v_inf *= Kms;
00117
00118
00119
00120 real sigma = rmin * rmin * (1 + 2 * Grav * mmerge * Msun
00121 / (rmin * Rsun * v_inf * v_inf));
00122
00123 real ymerge = (m1 * helium(m1) + m2 * helium(m2)) / mmerge;
00124 real mhemerge = mmerge * ymerge;
00125
00126
00127
00128 int i = (int) (N_MASS * (mmerge - M_MIN) / (M_MAX - M_MIN));
00129 if (i < 0) i = 0;
00130 if (i >= N_MASS) i = N_MASS - 1;
00131
00132 int j = (int) (N_HE * (ymerge - MIN_HE) / (MAX_HE - MIN_HE));
00133 if (j < 0) j = 0;
00134 if (j >= N_HE) j = N_HE - 1;
00135
00136 sigma_1[i][j] += sigma;
00137 sigma_err_sq_1[i][j] += sigma*sigma;
00138
00139 j = (int) (N_HEMASS * (mhemerge - M_HEMIN) / (M_HEMAX - M_HEMIN));
00140 if (j < 0) j = 0;
00141 if (j >= N_HEMASS) j = N_HEMASS - 1;
00142
00143 sigma_2[i][j] += sigma;
00144 sigma_err_sq_2[i][j] += sigma*sigma;
00145 }
00146
00147 #define SCALE 100
00148
00149 local void normalize_and_print_stats()
00150 {
00151 if (n_scatt <= 0) {
00152 cerr << "\nn_scatt = 0!\n";
00153 return;
00154 }
00155 int i, j;
00156
00157 real sum1 = 0, sum2 = 0;
00158 for (i = 0; i < N_MASS; i++) {
00159 for (j = 0; j < N_HE; j++) sum1 += sigma_1[i][j];
00160 for (j = 0; j < N_HEMASS; j++) sum2 += sigma_2[i][j];
00161 }
00162
00163 cerr << "\nNormalized differential cross sections "
00164 << "(row = 10*mass, column = scaled He):\n\n";
00165
00166 cerr << endl << SCALE << " sigma_1 (total = " << sum1/n_scatt
00167 << " pi Rsun^2):\n\n";
00168
00169 sum1 /= SCALE;
00170
00171 for (i = 0; i < N_MASS; i++) {
00172 for (j = 0; j < N_HE; j++)
00173 fprintf(stderr, " %7.3f", sigma_1[i][j]/sum1);
00174 cerr << endl;
00175 }
00176
00177 cerr << endl << SCALE << " sigma_2 (total = " << sum2/n_scatt
00178 << " pi Rsun^2):\n\n";
00179
00180 sum2 /= SCALE;
00181
00182 for (i = 0; i < N_MASS; i++) {
00183 for (j = 0; j < N_HEMASS; j++)
00184 fprintf(stderr, " %7.3f", sigma_2[i][j]/sum2);
00185 cerr << endl;
00186 }
00187
00188 cerr << "\nsigma_1 error:\n\n";
00189
00190 for (i = 0; i < N_MASS; i++) {
00191 for (j = 0; j < N_HE; j++)
00192 fprintf(stderr, " %7.3f", sqrt(sigma_err_sq_1[i][j])/sum1);
00193 cerr << endl;
00194 }
00195
00196 cerr << "\nsigma_2 error:\n\n";
00197
00198 for (i = 0; i < N_MASS; i++) {
00199 for (j = 0; j < N_HEMASS; j++)
00200 fprintf(stderr, " %7.3f", sqrt(sigma_err_sq_2[i][j])/sum2);
00201 cerr << endl;
00202 }
00203 }
00204
00205
00206
00207 main(int argc, char **argv)
00208 {
00209 int seed = 0;
00210 int n_rand = 0;
00211
00212 real v_inf = 10.0;
00213 int n_sigma2 = 100;
00214
00215 extern char *poptarg;
00216 int c;
00217 char* param_string = "l:L:n:N:s:u:U:v:x:";
00218
00219 while ((c = pgetopt(argc, argv, param_string)) != -1)
00220 switch(c) {
00221
00222 case 'l':
00223 case 'L': m_lower = atof(poptarg);
00224 break;
00225 case 'n': n_sigma2 = atoi(poptarg);
00226 break;
00227 case 'N': n_rand = atoi(poptarg);
00228 break;
00229 case 's': seed = atoi(poptarg);
00230 break;
00231 case 'u':
00232 case 'U': m_upper = atof(poptarg);
00233 break;
00234 case 'v': v_inf = atof(poptarg);
00235 break;
00236 case 'x': exponent = atof(poptarg);
00237 break;
00238 case '?': params_to_usage(cerr, argv[0], param_string);
00239 exit(1);
00240 }
00241
00242 cpu_init();
00243
00244 cerr << "\nVelocity at infinity = " << v_inf << " km/s.\n";
00245 cerr << "Mass range = " << m_lower << "-" << m_upper
00246 << " solar masses, power-law exponent = " << exponent
00247 << " (Salpeter = 1.35)\n";
00248 cerr << "Total number of mass combinations = " << n_sigma2 << endl;
00249
00250 int first_seed = srandinter(seed, n_rand);
00251 cerr << "Random seed = " << first_seed << endl;
00252
00253 initialize_stats();
00254
00255
00256
00257 for (int i = 0; i < n_sigma2; i++) {
00258
00259
00260
00261 real m1 = get_mass(m_lower, m_upper, -exponent - 1);
00262 real m2 = get_mass(m_lower, m_upper, -exponent - 1);
00263
00264
00265
00266 real r1 = radius(m1);
00267 real r2 = radius(m2);
00268
00269
00270
00271
00272 update_sigma2(m1, m2, r1, r2, v_inf);
00273 }
00274
00275 normalize_and_print_stats();
00276 }