00001
00002
00003
00004
00005
00006 #include "sigma3.h"
00007 #define DEBUG 0
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 #define N_HE 10
00019 #define MIN_HE 0.24 // MIN_HE and MAX_HE determine limits on mass for
00020 #define MAX_HE 0.39 // binning purposes only.
00021
00022 #define N_MASS 24
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 static real m_lower = 0.1;
00027 static real m_upper = 0.8;
00028 static real exponent = 1.35;
00029 static real m_unit;
00030
00031
00032
00033 #define N_INT 9
00034 static real m_int[N_INT] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.75, 0.8};
00035 static real r_int[N_INT] = {0.1, 0.2, 0.3, 0.4, 0.51, 0.63, 0.75, 1.09, 1.87};
00036 static real y_int[N_INT] = {0.240, 0.240, 0.243, 0.248, 0.254,
00037 0.273, 0.313, 0.347, 0.385};
00038
00039 static int n_scatt = 0;
00040 static int n_merge = 0;
00041 static int temp_counter[N_MASS][N_HE][N_RHO_ZONE_MAX];
00042
00043 static int total_counter[N_MASS][N_HE][N_RHO_ZONE_MAX];
00044 static real sigma[N_MASS][N_HE];
00045 static real sigma_err_sq[N_MASS][N_HE];
00046
00047
00048 local int get_index(real m)
00049 {
00050 for (int i = 0; i < N_INT; i++) if (m_int[i] > m) return i-1;
00051 return N_INT - 1;
00052 }
00053
00054
00055 local real get_quantity(real m, real* q)
00056 {
00057 int i = get_index(m);
00058
00059 if (i < 0)
00060 return q[0];
00061 else if (i >= N_INT-1)
00062 return q[N_INT-1];
00063
00064 return q[i] + (m - m_int[i]) * (q[i+1] - q[i]) / (m_int[i+1] - m_int[i]);
00065 }
00066
00067
00068 local real radius(real m)
00069 {
00070 return get_quantity(m, r_int);
00071 }
00072
00073
00074 local real helium(real m)
00075 {
00076 return get_quantity(m, y_int);
00077 }
00078
00079
00080
00081
00082
00083 local real get_mass(real ml, real mu, real x)
00084 {
00085 real r = randinter(0,1);
00086
00087 if (x == -1)
00088 return ml * exp( r*log(mu/ml) );
00089 else
00090 return ml * pow( 1 + r * (pow(mu/ml, 1+x) - 1), 1.0/(1+x));
00091 }
00092
00093
00094 local void zero_temp_counter()
00095 {
00096 for (int i = 0; i < N_MASS; i++)
00097 for (int j = 0; j < N_HE; j++)
00098 for (int k = 0; k < N_RHO_ZONE_MAX; k++) temp_counter[i][j][k] = 0;
00099 }
00100
00101
00102 local void initialize_stats()
00103 {
00104 for (int i = 0; i < N_MASS; i++)
00105 for (int j = 0; j < N_HE; j++) {
00106 sigma[i][j] = sigma_err_sq[i][j] = 0;
00107 for (int k = 0; k < N_RHO_ZONE_MAX; k++) total_counter[i][j][k] = 0;
00108 }
00109 }
00110
00111
00112
00113
00114
00115 local void accumulate_stats(scatter_profile& prof,
00116 initial_state3& init,
00117 intermediate_state3& inter,
00118 final_state3& final,
00119 int rho_bin)
00120 {
00121
00122 n_scatt++;
00123
00124 real mmerge = 0;
00125 real ymerge;
00126
00127 if (final.descriptor == merger_binary_1
00128 || final.descriptor == merger_escape_1) {
00129
00130 mmerge = prof.m2 + prof.m3;
00131 ymerge = (prof.m2 * helium(prof.m2*m_unit)
00132 + prof.m3 * helium(prof.m3*m_unit)) / mmerge;
00133
00134 } else if (final.descriptor == merger_binary_2
00135 || final.descriptor == merger_escape_2) {
00136
00137 real m1 = 1 - prof.m2;
00138 mmerge = m1 + prof.m3;
00139 ymerge = (m1 * helium(m1*m_unit)
00140 + prof.m3 * helium(prof.m3*m_unit)) / mmerge;
00141
00142 } else if (final.descriptor == merger_binary_3
00143 || final.descriptor == merger_escape_3) {
00144
00145 real m1 = 1 - prof.m2;
00146 mmerge = 1;
00147 ymerge = m1 * helium(m1*m_unit) + prof.m2 * helium(prof.m2*m_unit);
00148
00149 } else if (final.descriptor == triple_merger) {
00150
00151 real m2 = prof.m2;
00152 real m1 = 1 - m2;
00153 mmerge = 1 + prof.m3;
00154 ymerge = (m1 * helium(m1*m_unit) + m2 * helium(m2*m_unit)
00155 + prof.m3 * helium(prof.m3*m_unit)) / mmerge;
00156 }
00157
00158 if (mmerge > 0) {
00159 mmerge *= m_unit;
00160
00161 int i = (int) (N_MASS * (mmerge - M_MIN) / (M_MAX - M_MIN));
00162 if (i < 0) i = 0;
00163 if (i >= N_MASS) i = N_MASS - 1;
00164
00165 int j = (int) (N_HE * (ymerge - MIN_HE) / (MAX_HE - MIN_HE));
00166 if (j < 0) j = 0;
00167 if (j >= N_HE) j = N_HE - 1;
00168
00169 n_merge++;
00170
00171 temp_counter[i][j][rho_bin]++;
00172 }
00173 }
00174
00175
00176
00177
00178 local void normalize_and_store_counts(sigma_out& out, real weight)
00179 {
00180 for (int i = 0; i < N_MASS; i++)
00181 for (int j = 0; j < N_HE; j++) {
00182 real rho_sq_min, rho_sq_max;
00183 int k;
00184 for (k = 0, rho_sq_min = 0, rho_sq_max = out.rho_sq_init;
00185 k <= out.i_max;
00186 k++, rho_sq_min = rho_sq_max, rho_sq_max *= RHO_SQ_FACTOR) {
00187
00188 real factor = weight * (rho_sq_max - rho_sq_min)
00189 / out.trials_per_zone;
00190 sigma[i][j] += factor * temp_counter[i][j][k];
00191 sigma_err_sq[i][j] += factor * factor * temp_counter[i][j][k];
00192 total_counter[i][j][k] += temp_counter[i][j][k];
00193 }
00194 }
00195 }
00196
00197 local void print_stats(sigma_out& out)
00198 {
00199 int i, j;
00200
00201 cerr << "\nDifferential cross sections (n_scatt = " << n_scatt << "):\n";
00202
00203 cerr << "\nRaw counts (row = 10*mass, column = scaled He abundance"
00204 << " (total = " << n_merge << "):\n\n";
00205 for (i = 0; i < N_MASS; i++) {
00206 for (j = 0; j < N_HE; j++) {
00207 int total = 0;
00208 for (int k = 0; k <= out.i_max; k++)
00209 total += total_counter[i][j][k];
00210 fprintf(stderr, " %7d", total);
00211 }
00212 cerr << endl;
00213 }
00214
00215 cerr << "\nsigma / (pi a^2):\n\n";
00216 for (i = 0; i < N_MASS; i++) {
00217 for (j = 0; j < N_HE; j++)
00218 fprintf(stderr, " %7.3f", sigma[i][j]);
00219 cerr << endl;
00220 }
00221
00222 cerr << "\n(sigma error) / (pi a^2):\n\n";
00223 for (i = 0; i < N_MASS; i++) {
00224 for (j = 0; j < N_HE; j++)
00225 fprintf(stderr, " %7.3f", sqrt(sigma_err_sq[i][j]));
00226 cerr << endl;
00227 }
00228 }
00229
00230 main(int argc, char **argv)
00231 {
00232 int debug = 0;
00233 int seed = 0;
00234 int n_rand = 0;
00235 real max_trial_density = 1.0;
00236
00237 real cpu_time_check = 3600;
00238 real dt_snap = VERY_LARGE_NUMBER;
00239 real snap_cube_size = 10;
00240 int scatter_summary_level = 0;
00241
00242 real sma = 1.0;
00243 real v_inf = 10.0;
00244
00245 int n_sigma3 = 1;
00246 bool sig_print = FALSE;
00247 bool stat_print = 0;
00248
00249 scatter_profile prof;
00250 make_standard_profile(prof);
00251
00252 extern char *poptarg;
00253 int c;
00254 char* param_string ="a:A:c:C:D:d:e:l:L:n:N:p:PqQs:u:U:v:x:";
00255
00256 while ((c = pgetopt(argc, argv, param_string)) != -1)
00257 switch(c)
00258 {
00259 case 'a': sma = atof(poptarg);
00260 break;
00261 case 'A': prof.eta = atof(poptarg);
00262 break;
00263 case 'c': cpu_time_check = 3600*atof(poptarg);
00264 break;
00265 case 'C': snap_cube_size = atof(poptarg);
00266 break;
00267 case 'd': max_trial_density = atof(poptarg);
00268 break;
00269 case 'D': dt_snap = atof(poptarg);
00270 scatter_summary_level = 2;
00271 break;
00272 case 'e': prof.ecc = atof(poptarg);
00273 prof.ecc_flag = 1;
00274 break;
00275 case 'l':
00276 case 'L': m_lower = atof(poptarg);
00277 break;
00278 case 'n': n_sigma3 = atoi(poptarg);
00279 break;
00280 case 'N': n_rand = atoi(poptarg);
00281 break;
00282 case 'p': stat_print = atoi(poptarg);
00283 if (stat_print <= 0) stat_print = 1;
00284 break;
00285 case 'P': sig_print = 1 - sig_print;
00286 stat_print = 1;
00287 break;
00288 case 'q': if (scatter_summary_level > 0)
00289 scatter_summary_level = 0;
00290 else
00291 scatter_summary_level = 1;
00292 break;
00293 case 'Q': if (scatter_summary_level > 0)
00294 scatter_summary_level = 0;
00295 else
00296 scatter_summary_level = 2;
00297 break;
00298 case 's': seed = atoi(poptarg);
00299 break;
00300 case 'u':
00301 case 'U': m_upper = atof(poptarg);
00302 break;
00303 case 'v': v_inf = atof(poptarg);
00304 break;
00305 case 'V': debug = atoi(poptarg);
00306 break;
00307 case 'x': exponent = atof(poptarg);
00308 break;
00309 case '?': params_to_usage(cerr, argv[0], param_string);
00310 exit(1);
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
00320 cpu_init();
00321
00322 cerr << "\n\t*** "
00323 << "Binary/single-star scattering with stellar collisions."
00324 << " ***\n\n";
00325 cerr << "Binary semi-major-axis a = " << sma
00326 << " A.U. Velocity at infinity = " << v_inf << " km/s.\n";
00327 cerr << "Mass range = " << m_lower << "-" << m_upper
00328 << " solar masses, power-law exponent = " << exponent
00329 << " (Salpeter = 1.35)\n";
00330 cerr << "Target trial density = " << max_trial_density
00331 << ", total number of mass combinations = " << n_sigma3 << endl;
00332
00333 int first_seed = srandinter(seed, n_rand);
00334 cerr << "Random seed = " << first_seed << endl;
00335
00336 sigma_out out;
00337 initialize_stats();
00338
00339
00340
00341 for (int i = 0; i < n_sigma3; i++) {
00342
00343
00344
00345 real m1 = get_mass(m_lower, m_upper, -exponent - 1);
00346 real m2 = get_mass(m_lower, m_upper, -exponent - 1);
00347 real m3 = get_mass(m_lower, m_upper, -exponent - 1);
00348
00349
00350
00351 m_unit = m1 + m2;
00352 real r_unit = sma;
00353 real v_unit = sqrt( (Grav * Msun / AU)
00354 * m1 * m2 * (m1 + m2 + m3) / ((m1 + m2) * m3)
00355 / sma ) / Kms;
00356
00357 prof.m2 = m2 / m_unit;
00358 prof.m3 = m3 / m_unit;
00359 prof.v_inf = v_inf / v_unit;
00360
00361 prof.r1 = radius(m1) * Rsun / (sma * AU);
00362 prof.r2 = radius(m2) * Rsun / (sma * AU);
00363 prof.r3 = radius(m3) * Rsun / (sma * AU);
00364
00365 int p = cerr.precision(STD_PRECISION);
00366 cerr << "\nMass combination #" << i+1 << ":\n";
00367 cerr << " m1 = " << m1 << " m2 = " << m2
00368 << " m3 = " << m3 << " solar\n";
00369 cerr << " r1 = " << radius(m1) << " r2 = " << radius(m2)
00370 << " r3 = " << radius(m3) << " solar\n";
00371 cerr << " a = " << sma << " A.U. = "
00372 << sma * AU / Rsun << " solar,";
00373 cerr << " v_inf = " << v_inf << " km/s = "
00374 << prof.v_inf << " scaled\n";
00375
00376
00377
00378
00379
00380 zero_temp_counter();
00381 get_sigma3(max_trial_density, prof, out,
00382 debug, cpu_time_check,
00383 dt_snap, snap_cube_size,
00384 scatter_summary_level,
00385 accumulate_stats);
00386
00387
00388
00389
00390 normalize_and_store_counts(out, 1.0/n_sigma3);
00391
00392
00393
00394 if (sig_print) print_sigma3(out, prof.v_inf * prof.v_inf);
00395 if (stat_print > 0 && (i+1)%stat_print == 0) print_stats(out);
00396
00397 cerr.precision(p);
00398 }
00399
00400 print_stats(out);
00401 }