Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

scatt_stats_2a.C

Go to the documentation of this file.
00001 
00002 // scatt_stats_2a.C: Determine merger cross-sections for 2-body encounters
00003 //                   Steve McMillan, Charles Bailyn (Sep 1994)
00004 
00005 // Starlab application:  no library function.
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 // Bin final results in:
00019 //      (1) total mass and helium abundance
00020 //      (2) total mass and helium mass.
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;    // Convention: Salpeter = +1.35!
00037 static real m_unit;
00038 
00039 // Interpolation from real stellar models:
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)       // Mass-radius relation (units: solar)
00074 {
00075     return get_quantity(m, r_int);
00076 }
00077 
00078 
00079 local real helium(real m)       // Helium fraction (mass unit = solar mass)
00080 {
00081     return get_quantity(m, y_int);
00082 }
00083 
00084 // get_mass: Return a random mass between ml and mu, distributed as a
00085 //           power law with exponent x (i.e. dN/dm \propto m^x).
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 // Zero out accumulators:
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     // Express sig in solar units (PI Rsun^2):
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     // Bin the new cross section:
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;  // Relative velocity at infinity in km/s
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     // Loop over mass combinations, obtaining cross-sections for each.
00256 
00257     for (int i = 0; i < n_sigma2; i++) {
00258 
00259         // Get masses in solar masses, randomly from the mass function.
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         // Get radii in solar radii.
00265 
00266         real r1 = radius(m1);
00267         real r2 = radius(m2);
00268 
00269         // Update cross-sections, assuming that all mass combinations
00270         // carry equal statistical weight.
00271 
00272         update_sigma2(m1, m2, r1, r2, v_inf);
00273     }
00274 
00275     normalize_and_print_stats();
00276 }

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