Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

rate_stats.C

Go to the documentation of this file.
00001 
00002 // rate_stats.C: Determine Maxwellian averaged cross-sections for 3-body
00003 //               scattering.  Input in dimensionless units only.
00004 //
00005 //               Steve McMillan, Piet Hut, Fred Rasio (July 1994)
00006 
00007 // Starlab application:  get_rate3.
00008 
00009 #ifdef TOOLBOX
00010 #include "sigma3.h"
00011 
00012 #define USAGE "usage: rate_stats \
00013 [-A #] [-d #] [-e #] [-m #] [-M #] [-n #] [-r[123] # ] [-s #] [-v #] \n"
00014 
00015 //------------------------------------------------------------------------
00016 
00017 // Local statistics data:
00018 
00019 #define NA      10
00020 #define NE      10
00021 #define N1      50
00022 
00023 static int n_hit = 0;
00024 static int counter[NA][NE][N_RHO_ZONE_MAX];     // Raw counts
00025 static int ecounter[N1][N_RHO_ZONE_MAX];
00026 static int vcounter[N1][N_RHO_ZONE_MAX];
00027 
00028 static real sigma[NA][NE];                      // Maxwellian averaged sigma
00029 static real sigma_err_sq[NA][NE];
00030 static real esigma[N1];
00031 static real vsigma[N1];
00032 static real v_scale = 1;
00033 
00034 local void initialize_local_stats()     // Initialize overall integrals
00035 {
00036     for (int ia = 0; ia < NA; ia++)
00037         for (int je = 0; je < NE; je++)
00038             sigma[ia][je] = sigma_err_sq[ia][je] = 0;
00039 
00040     for (int i1 = 0; i1 < N1; i1++)
00041         esigma[i1] = vsigma[i1] = 0;
00042 }
00043 
00044 local void initialize_local_counters()  // Initialize counters for specific v
00045 {
00046     int kr;
00047 
00048     for (int ia = 0; ia < NA; ia++)
00049         for (int je = 0; je < NE; je++)
00050             for (kr = 0; kr < N_RHO_ZONE_MAX; kr++)
00051                 counter[ia][je][kr] = 0;
00052 
00053     for (int i1 = 0; i1 < N1; i1++)
00054         for (kr = 0; kr < N_RHO_ZONE_MAX; kr++)
00055             ecounter[i1][kr] = vcounter[i1][kr] = 0;
00056 }
00057 
00058 local real v_recoil(initial_state3& init, final_state3& final)
00059 {
00060     // Determine the recoil velocity of the final binary.
00061 
00062     real m_total = 1 + init.m3;
00063     real m2i = init.m2;
00064     real m1i = 1 - m2i;
00065     real m3i = init.m3;
00066 
00067     // Find the indices of the remaining bound stars in the "system" array:
00068 
00069     int i1f = 0, i2f = 1;
00070     if (final.system[0].index == final.escaper) {
00071         i1f = 2;
00072     } else if (final.system[1].index == final.escaper) {
00073         i2f = 2;
00074     }
00075 
00076     real m1f = final.system[i1f].mass;
00077     real m2f = final.system[i2f].mass;
00078     real m3f = m_total - m1f - m2f;
00079 
00080     real de = m1f*m2f/final.sma - m1i*m2i/init.sma;     // N.B. init.sma = 1.
00081     real vinff = sqrt(max( (2*m_total*de + (m1i+m2i)*m3i*init.v_inf*init.v_inf)
00082                              / ((m1f+m2f)*m3f), 0.0));
00083 
00084     return m3f*vinff/m_total;
00085 }
00086 
00087 // accumulate_local_stats: Gather statistics supplied by get_sigma3.
00088 //                         Customize here to the specific application at hand.
00089 
00090 local void accumulate_local_stats(scatter_profile& prof,
00091                                   initial_state3& init,
00092                                   intermediate_state3& inter,
00093                                   final_state3& final,
00094                                   int rho_bin,
00095                                   sigma_out& out)
00096 {
00097     if (final.descriptor == exchange_1 || final.descriptor == exchange_2) {
00098 
00099         if (prof.r3 > 0) {
00100 
00101             real ratio = final.sma / prof.r3;
00102 
00103             int ia = (int) (log(ratio) / log(2.0));
00104             if (ia >= NA) ia = NA - 1;
00105 
00106             int je = (int) (NE * final.ecc);
00107             if (je >= NE) je = NE - 1;
00108 
00109             counter[ia][je][rho_bin]++;
00110             n_hit++;
00111 
00112             // Higher resolution ecentricity:
00113 
00114             int i1 = (int) (N1 * final.ecc);
00115             if (i1 >= N1) i1 = N1 - 1;
00116             ecounter[i1][rho_bin]++;
00117 
00118             // Recoil velocity:
00119 
00120             i1 = (int) (N1 * v_recoil(init, final) / v_scale);
00121             if (i1 >= N1) i1 = N1 - 1;
00122             vcounter[i1][rho_bin]++;
00123         }
00124     }
00125 }
00126 
00127 local void integrate_local_stats(sigma_out& out, real weight)
00128 {
00129     for (int ia = 0; ia < NA; ia++)
00130         for (int je = 0; je < NE; je++) {
00131 
00132             // Normalize the current counts to dsigma and dsigma_err_eq...
00133 
00134             real dsigma = 0;
00135             real dsigma_err_sq = 0;
00136 
00137             // Standard normalization, from sigma3:
00138 
00139             real rho_sq_min, rho_sq_max;
00140             int kr;
00141             for (kr = 0, rho_sq_min = 0, rho_sq_max = out.rho_sq_init;
00142                  kr <= out.i_max;
00143                  kr++, rho_sq_min = rho_sq_max, rho_sq_max *= RHO_SQ_FACTOR) {
00144 
00145                 real factor = (rho_sq_max - rho_sq_min) / out.trials_per_zone;
00146                 dsigma += factor * counter[ia][je][kr];
00147                 dsigma_err_sq += factor * factor * counter[ia][je][kr];
00148             }
00149 
00150             // ...then update the integrals (add errors in quadrature).
00151             // Integration is the same as in get_rate3 below.
00152 
00153             sigma[ia][je] += dsigma * weight;
00154             sigma_err_sq[ia][je] += dsigma_err_sq * weight * weight;
00155         }
00156 
00157     for (int i1 = 0; i1 < N1; i1++) {
00158 
00159         // Normalize the current counts to desigma and dvsigma...
00160 
00161         real desigma = 0;
00162         real dvsigma = 0;
00163 
00164         real rho_sq_min, rho_sq_max;
00165         int kr;
00166         for (kr = 0, rho_sq_min = 0, rho_sq_max = out.rho_sq_init;
00167              kr <= out.i_max;
00168              kr++, rho_sq_min = rho_sq_max, rho_sq_max *= RHO_SQ_FACTOR) {
00169 
00170             real factor = (rho_sq_max - rho_sq_min) / out.trials_per_zone;
00171             desigma += factor * ecounter[i1][kr];
00172             dvsigma += factor * vcounter[i1][kr];
00173         }
00174 
00175         // Integration:
00176 
00177         esigma[i1] += desigma * weight;
00178         vsigma[i1] += dvsigma * weight;
00179     }
00180 }
00181 
00182 local void print_local_stats()
00183 {
00184     int ia, je, i1;
00185 
00186     cerr << "\nDifferential cross sections:\n";
00187 
00188     cerr << "\n<v sigma> / (pi a^2 v_rel_th)\n\n";
00189     for (ia = 0; ia < NA; ia++) {
00190         for (je = 0; je < NE; je++)
00191             fprintf(stderr, " %7.3f", sigma[ia][je]);
00192         cerr << endl;
00193     }
00194 
00195     cerr << "\n(<v sigma> error) / (pi a^2 v_rel_th)\n\n";
00196     for (ia = 0; ia < NA; ia++) {
00197         for (je = 0; je < NE; je++)
00198             fprintf(stderr, " %7.3f", sqrt(sigma_err_sq[ia][je]));
00199         cerr << endl;
00200     }
00201 
00202     cerr << "\n<v sigmae> / (pi a^2 v_rel_th)\n\n";
00203     for (i1 = 0; i1 < N1; i1++) fprintf(stderr, " %7.3f", esigma[i1]);
00204     cerr << endl;
00205 
00206     cerr << "\n<v sigmav> / (pi a^2 v_rel_th)\n\n";
00207     for (i1 = 0; i1 < N1; i1++) fprintf(stderr, " %7.3f", vsigma[i1]);
00208     cerr << endl;
00209 }
00210 
00211 //------------------------------------------------------------------------
00212 
00213 local real stat_weight(real v, real v_th_3d) // $v^3 f(v)$
00214 {
00215     // Return the normalized Maxwellian distribution function at velocity v.
00216 
00217     real x = v/v_th_3d;
00218     return 3 * sqrt(6/PI) * x * x * x * exp(-1.5*x*x);
00219 
00220     // Normalization is such that $\int v^2 f(v) dv = 1$
00221     //                        and $\int v^4 f(v) dv = v_{th,3d}^2$
00222 }
00223 
00224 local int get_rate3(scatter_profile& prof, real v_rel_th,
00225                     int nv, real max_dens,
00226                     real total_sigma[][N_FINAL], real total_err_sq[][N_FINAL])
00227 {
00228     real v_max = 2 * v_rel_th;
00229     real dv = v_max / nv;
00230 
00231     int ii, jj;
00232 
00233     // Initialize "standard" counters...
00234 
00235     int total_trials = 0;
00236 
00237     for (ii = 0; ii < N_INTER; ii++)
00238         for (jj = 0; jj < N_FINAL; jj++) {
00239             total_sigma[ii][jj] = 0;
00240             total_err_sq[ii][jj] = 0;
00241         }
00242 
00243     // ...and extra ones:
00244 
00245     initialize_local_stats();
00246 
00247     // Perform the integration using the trapezoid rule in v_inf
00248     // (skip the end-points at 0 and 2 v_max):
00249 
00250     for (int i = 1; i < nv; i++) {
00251 
00252         prof.v_inf = i * dv;
00253 
00254         initialize_local_counters();
00255 
00256         sigma_out out;
00257         get_sigma3(max_dens, prof, out,
00258                    0,                   // debug
00259                    VERY_LARGE_NUMBER,   // cpu_time_check
00260                    VERY_LARGE_NUMBER,   // dt_snap
00261                    VERY_LARGE_NUMBER,   // snap_cube_size
00262                    0,                   // scatter_summary_level
00263                    accumulate_local_stats);
00264 
00265         total_trials += out.total_trials;
00266 
00267         // Accumulate the standard integrals...
00268 
00269         real weight = stat_weight(prof.v_inf, v_rel_th) * dv / v_rel_th;
00270 
00271         for (ii = 0; ii < N_INTER; ii++)
00272             for (jj = 0; jj < N_FINAL; jj++) {
00273 
00274                 total_sigma[ii][jj] += out.sigma[ii][jj] * weight;
00275 
00276                 // Just add errors in quadrature (sqrt taken at end):
00277 
00278                 total_err_sq[ii][jj] += out.sigma_err_sq[ii][jj]
00279                                         * weight * weight;
00280                 }
00281 
00282         // ...and the integrals for differential cross-sections:
00283 
00284         integrate_local_stats(out, weight);
00285 
00286         // (Note that the unit of sigma here is pi a^2 v_rel_th.)
00287     }
00288 
00289     return total_trials;
00290 }
00291 
00292 local real total_coll(real total_sigma[][N_FINAL])
00293 {
00294     real sigma_coll = 0;        
00295 
00296     for (int i_int = 0; i_int < N_INTER; i_int++)
00297         sigma_coll += total_sigma[i_int][merger_binary_1]
00298                             + total_sigma[i_int][merger_binary_2]
00299                             + total_sigma[i_int][merger_binary_3]
00300                             + total_sigma[i_int][merger_escape_1]
00301                             + total_sigma[i_int][merger_escape_2]
00302                             + total_sigma[i_int][merger_escape_3]
00303                             + total_sigma[i_int][triple_merger];
00304     return sigma_coll;
00305 }
00306 
00307 main(int argc, char **argv) {
00308 
00309     scatter_profile prof;
00310     make_standard_profile(prof);
00311 
00312     // Default parameters:
00313 
00314     int  seed   = 0;
00315     prof.m2 = prof.m3 = 0.5;
00316     prof.r1 = prof.r2 = prof.r3 = 0;
00317     real v_rel_th = 1;                  // 3-D rms relative velocity
00318 
00319     real max_dens = 64;                 // Best joint choice of parameters?
00320     int nv = 6;
00321 
00322     // Parse the command line:
00323 
00324     int i = 0;
00325     while (++i < argc) if (argv[i][0] == '-')
00326         switch (argv[i][1]) {
00327             case 'A': prof.eta = atof(argv[++i]);
00328                       break;
00329             case 'd': max_dens = atoi(argv[++i]);
00330                       break;
00331             case 'e': prof.ecc = atof(argv[++i]);
00332                       prof.ecc_flag = 1;
00333                       break;
00334             case 'm': prof.m2 = atof(argv[++i]);
00335                       break;
00336                       break;
00337             case 'M': prof.m3 = atof(argv[++i]);
00338                       break;
00339             case 'n': nv = atoi(argv[++i]);
00340                       break;
00341             case 'r': switch(argv[i][2]) {
00342                           case '1':     prof.r1 = atof(argv[++i]);
00343                                         break;
00344                           case '2':     prof.r2 = atof(argv[++i]);
00345                                         break;
00346                           case '3':     prof.r3 = atof(argv[++i]);
00347                                         break;
00348                       }
00349                       if (prof.r3 < 0)
00350                           err_exit("r3 < 0"); // To avoid bus error in
00351                                               // optimized g++ 2.3.3!
00352                       break;
00353             case 's': seed = atoi(argv[++i]);
00354                       break;
00355             case 'v': v_rel_th = atof(argv[++i]);
00356                       break;
00357             default:  cerr << USAGE;
00358                       exit(1);
00359         }
00360 
00361     if (prof.r3 <= 0) err_exit("rate_stats: must specify r3 > 0.");
00362 
00363     int first_seed = srandinter(seed);
00364     cerr << "Thermally averaged reaction rates, random seed = "
00365          << first_seed << endl;
00366 
00367     // Output information on the scatter profile:
00368 
00369     prof.v_inf = -1;
00370     print_profile(cerr, prof);
00371 
00372     cerr << "binary eccentricity = ";
00373     if (prof.ecc_flag)
00374         cerr << prof.ecc;
00375     else
00376         cerr << "thermal [f(e) = 2e]";
00377 
00378     cerr << "   v_rel_th = " << v_rel_th << endl;
00379 
00380     real total_sigma[N_INTER][N_FINAL];
00381     real total_err_sq[N_INTER][N_FINAL];
00382 
00383     // Calculate the Maxwellian-averaged cross sections:
00384 
00385     v_scale = 4 * v_rel_th;
00386     int total_trials = get_rate3(prof, v_rel_th, nv, max_dens,
00387                                  total_sigma, total_err_sq);
00388 
00389     // Display the results:
00390 
00391     cerr << "\nmax_dens = " << max_dens
00392          << "  nv = " << nv
00393          << "  total_trials = " << total_trials
00394          << "  (" << n_hit << " hits)\n\n";
00395 
00396     cerr << "<v sigma> (unit = pi a^2 v_rel_th):\n\n";
00397     print_sigma3_array(total_sigma, 1);
00398 
00399     cerr << "<v sigma_err> (unit = pi a^2 v_rel_th):\n\n";
00400     print_sigma3_err_array(total_err_sq, 1);
00401 
00402     // More detail:
00403 
00404     cerr << "<v sigma> and <v sigma_err> (details):\n\n";
00405     print_sigma3_nonmergers(total_sigma, total_err_sq, 1);
00406 
00407     if (total_coll(total_sigma) > 0) 
00408         print_sigma3_mergers(total_sigma, total_err_sq, 1);
00409 
00410     // Finally, print the differential cross sections:
00411 
00412     print_local_stats();
00413 }
00414 #endif

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