Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

test_2.C

Go to the documentation of this file.
00001 
00002 // test_2.C: Determine merger cross-sections for two-body collisions.
00003 
00004 // Starlab application:  get_sigma3.
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;    // Convention: Salpeter = +1.35!
00029 static real m_unit;
00030 
00031 // Interpolation from real stellar models:
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)       // Mass-radius relation (units: solar)
00069 {
00070     return get_quantity(m, r_int);
00071 }
00072 
00073 
00074 local real helium(real m)       // Helium fraction (mass unit = solar mass)
00075 {
00076     return get_quantity(m, y_int);
00077 }
00078 
00079 
00080 // get_mass: Return a random mass between ml and mu, distributed as a
00081 //           power law with exponent x (i.e. dN/dm \propto m^x).
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 // accumulate_stats: Gather statistics supplied by get_sigma3. Customize here
00113 //                   to the specific application at hand.
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) {        // 2 and 3 merged
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) { // 1 and 3 merged
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) { // 1 and 2 merged
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) {      // 1, 2 and 3 merged
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 // normalize_and_store_counts: convert raw counts into cross-sections and
00176 //                             errors, and add them into the total
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; // One check per CPU hour!
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;     // Binary semi-major axis in A.U.
00243     real v_inf = 10.0;  // Relative velocity at infinity in km/s
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);// (Specify in hours)
00264                       break;
00265             case 'C': snap_cube_size = atof(poptarg);
00266                       break;
00267             case 'd': max_trial_density = atof(poptarg);  // Max density for a
00268                       break;                              // single experiment
00269             case 'D': dt_snap = atof(poptarg);
00270                       scatter_summary_level = 2;  // Undo with later "-q/Q"
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     // Debugging:    |debug| = 0 ==> no debugging output
00314     //               |debug| = 1 ==> output only at end (default)
00315     //               |debug| = 2 ==> output at end of each top-level iteration
00316     //               |debug| = 3 ==> output after each sub-trial
00317     //
00318     //                debug  < 0 ==> simple statistics also (default: off)
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     // Loop over mass combinations, obtaining cross-sections for each.
00340 
00341     for (int i = 0; i < n_sigma3; i++) {
00342 
00343         // Get masses in solar masses, randomly from the mass function.
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         // Scale masses, v_inf and radii:
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         // Get cross-sections. Note that the primary use of get_sigma3
00377         // here is to ensure that properly sampled data are sent to
00378         // routine accumulate_stats.
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         // We are assuming here that all mass combinations carry
00388         // equal statistical weight.
00389 
00390         normalize_and_store_counts(out, 1.0/n_sigma3);
00391 
00392         // Optional diagnostic/intermediate output:
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 }

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