Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

all_sig.C

Go to the documentation of this file.
00001 
00002 // all_sig.C:   Generate cross sections and statistics on point-mass
00003 //              encounters for identical binary components and
00004 //              arbitrary incoming mass.
00005 //
00006 //              Determine:      (1) Total cross-sections, broken down by type:
00007 //                                      0 flybys (energy exchange only)
00008 //                                      1 exchange
00009 //                                      2 hierarchical resonance
00010 //                                      3 "strong" resonance (n_ocs >= MIN_OSC)
00011 //                                      4 "weak" resonant preservation
00012 //                                      5 "weak" resonant exchange
00013 //                              (2) Differential cross-sections in
00014 //                                      energy exchange dE/E
00015 //                                      final a and e (2-D),
00016 //                                  both broken down by type
00017 
00018 // Starlab application:  get_sigma3.
00019 
00020 #include "sigma3.h"
00021 
00022 #define MIN_OSC 4
00023 
00024 // Global statistics data:
00025 
00026 #define NTYPE           6       // number of defined outcome types
00027 
00028 #define DE_MIN          0.01    // starting point for dE/E binning
00029 #define EBINS_PER_DECADE  5     // number of bins per decade in dE/E
00030 #define N_DECADES       3       // number of decades spanned in dE/E
00031 #define NE      EBINS_PER_DECADE * N_DECADES    // number of bins in dE/E
00032 
00033 #define A_MIN_DEF       0.17677669529663688110  // = sqrt(2)/8
00034 real a_min = A_MIN_DEF;
00035                                 // starting point for final sma binning
00036 #define ABINS_PER_DOUBLING  2   // number of bins per doubling in sma
00037 #define NSMA            10      // number of bins in sma 
00038 
00039 #define NECC            5       // number of bins in final eccentricity^2
00040 
00041 #define NR      N_RHO_ZONE_MAX  // (for brevity)
00042 
00043 // Counters:
00044 
00045 static int n_total[NTYPE][NR];
00046 static int ne[NE+1][NTYPE][NR];
00047 static int nae[NSMA][NECC][NTYPE][NR];
00048 
00049 static int total_trials[NR];    // Keep track of progress locally.
00050 static int total_total;
00051 
00052 static bool print_counts = FALSE;
00053 static int output_frequency = -1;
00054 
00055 // Initialize all counters:
00056 
00057 local void initialize_stats()
00058 {
00059     for (int type = 0; type < NTYPE; type++)
00060         for (int kr = 0; kr < NR; kr++) {
00061             n_total[type][kr] = 0;
00062             for (int je = 0; je < NE; je++) ne[je][type][kr] = 0;
00063             for (int ja = 0; ja < NSMA; ja++)
00064                 for (int ke = 0; ke < NECC; ke++)
00065                     nae[ja][ke][type][kr] = 0;
00066         }
00067 
00068     for (int kr = 0; kr < NR; kr++) total_trials[kr] = 0;
00069     total_total = 0;
00070 }
00071 
00072 // print_stats:  Convert raw counts into final data and print them out.
00073 //               Weights are provided by a library routine to minimise
00074 //               duplication in functionality and to allow the internal
00075 //               workings of the package to change without affecting
00076 //               user-written code.
00077 
00078 local void print_stats(scatter_profile& prof, sigma_out& out)
00079 {
00080     char* s[NTYPE] = {"non-resonant preservations   ",
00081                       "non-resonant exchanges       ",
00082                       "hierarchical resonances      ",
00083                       "strong democratic resonances ",
00084                       "weak democratic preservations",
00085                       "weak democratic exchanges    "};
00086 
00087     real v2 = prof.v_inf * prof.v_inf;
00088 
00089     cerr << "\n--------------- CROSS-SECTIONS BY TYPE ---------------\n";
00090 
00091     for (int type = 0; type < NTYPE; type++) {
00092 
00093         cerr << endl << "**** " << s[type] << "\n\n";
00094 
00095         real sigma, error, dsig[NE], derr[NE],
00096              dsig2[NSMA][NECC+1], derr2[NSMA][NECC+1];
00097         int je, ja, ke;
00098 
00099         sigma = error = 0;
00100 
00101         for (je = 0; je < NE; je++) dsig[je] = derr[je] = 0;
00102 
00103         for (ja = 0; ja < NSMA; ja++)
00104             for (ke = 0; ke <= NECC; ke++) dsig2[ja][ke] = derr2[ja][ke] = 0;
00105 
00106         for (int kr = 0; kr <= out.i_max; kr++) {
00107 
00108             real w = zone_weight(out, kr);  // = zone_area / trials_per_zone
00109             real w2 = w * w;
00110 
00111             sigma += w * n_total[type][kr];
00112             error += w2 * n_total[type][kr];
00113 
00114             for (je = 0; je < NE; je++) {
00115                 dsig[je] += w * ne[je][type][kr];
00116                 derr[je] += w2 * ne[je][type][kr];
00117             }
00118 
00119             for (ja = 0; ja < NSMA; ja++)
00120                 for (ke = 0; ke < NECC; ke++) {
00121                     dsig2[ja][ke] += w * nae[ja][ke][type][kr];
00122                     derr2[ja][ke] += w2 * nae[ja][ke][type][kr];
00123                     dsig2[ja][NECC] += w * nae[ja][ke][type][kr];
00124                     derr2[ja][NECC] += w2 * nae[ja][ke][type][kr];
00125                 }
00126         }
00127 
00128         cerr << "v^2 sigma = " << v2 * sigma << endl;
00129 
00130         if (sigma > 0) {
00131 
00132             cerr << "v^2 error = " << v2 * sqrt(error) << endl;
00133 
00134             cerr << "\nv^2 dsig(E)/dE (dE_min = " << DE_MIN
00135                  <<  ", " << EBINS_PER_DECADE << " bins per decade):\n\n";
00136             int je1, je2;
00137             real e_fac = pow(10.0, 1.0/EBINS_PER_DECADE);
00138             for (je1 = 0, je = 0; je1 < N_DECADES; je1++) {
00139                 real e1 = DE_MIN, e2 = DE_MIN;
00140                 for (je2 = 0; je2 < EBINS_PER_DECADE; je2++, je++) {
00141                     e2 *= e_fac;
00142                     fprintf(stderr, " %11.7f", v2*dsig[je]/(e2-e1));
00143                     e1 = e2;
00144                 }
00145                 cerr << endl;
00146             }
00147 
00148             cerr << "\nv^2 derr(E)/dE:\n\n";
00149             for (je1 = 0, je = 0; je1 < N_DECADES; je1++) {
00150                 real e1 = DE_MIN, e2 = DE_MIN;
00151                 for (je2 = 0; je2 < EBINS_PER_DECADE; je2++, je++) {
00152                     e2 *= e_fac;
00153                     fprintf(stderr, " %11.7f", v2*sqrt(derr[je])/(e2-e1));
00154                     e1 = e2;
00155                 }
00156                 cerr << endl;
00157             }
00158 
00159             cerr << "\n" << NECC
00160                  << " v^2 dsig2(a,e) / v^2 dsig2(a)" << endl
00161                  << "(a -->, a_min = " << a_min
00162                  << ", " << ABINS_PER_DOUBLING
00163                  << " bins per doubling; linear in e^2):\n\n";
00164 
00165             for (ke = 0; ke <= NECC; ke++) {
00166                 for (ja = 0; ja < NSMA; ja++) {
00167 
00168                     real average = v2*dsig2[ja][NECC] / NECC;
00169                     real dsig = v2*dsig2[ja][ke];
00170                     if (ke < NECC && average > 0) dsig /= average;
00171 
00172                     fprintf(stderr, "%7.3f", min(99.999, dsig));
00173                 }
00174 
00175                 if (ke == 0)      fprintf(stderr, "    e = 0");
00176                 if (ke == NECC-1) fprintf(stderr, "    e = 1\n");
00177                 if (ke == NECC)   fprintf(stderr, "    total");
00178                 cerr << endl;
00179             }
00180 
00181             cerr << "\n" << NECC << " v^2 derr2(a,e) / v^2 dsig2(a):\n\n";
00182 
00183             for (ke = 0; ke <= NECC; ke++) {
00184                 for (ja = 0; ja < NSMA; ja++) {
00185 
00186                     real average = v2*dsig2[ja][NECC] / NECC;
00187                     real derr = v2*sqrt(derr2[ja][ke]);
00188                     if (ke < NECC && average > 0) derr /= average;
00189                     
00190                     fprintf(stderr, "%7.3f", min(99.999, derr));
00191                 }
00192                 if (ke == NECC-1) cerr << endl;
00193                 cerr << endl;
00194             }
00195         }
00196     }
00197     cerr << endl;
00198 }
00199 
00200 local real log2(real x)
00201 {
00202     return log(x)/log(2.0);
00203 }
00204 
00205 // accumulate_stats: Gather statistics supplied by get_sigma3.
00206 //                   Control will be transferred here after each scattering;
00207 //                   all relevent state information and the rho zone used
00208 //                   are provided by get_sigma3.
00209 //                   Customize here to the specific application at hand.
00210 
00211 local void accumulate_stats(scatter_profile& prof,
00212                             initial_state3& init,
00213                             intermediate_state3& inter,
00214                             final_state3& final,
00215                             int rho_zone,
00216                             sigma_out& out)
00217 {
00218     // Divide into types and determine binning:
00219 
00220     if (inter.n_stars == 3
00221         && inter.descriptor != unknown_intermediate
00222         && final.descriptor != error
00223         && final.descriptor != stopped
00224         && final.descriptor != unknown_final) {
00225 
00226         // Type:
00227 
00228         int type = -1;
00229         if (inter.descriptor == non_resonance) {
00230             if (final.descriptor == preservation)
00231                 type = 0;
00232             else
00233                 type = 1;
00234         } else if (inter.descriptor == hierarchical_resonance)
00235             type = 2;
00236         else if (inter.descriptor == democratic_resonance) {
00237             if (inter.n_osc >= MIN_OSC)
00238                 type = 3;
00239             else {
00240                 if (final.descriptor == preservation)
00241                     type = 4;
00242                 else
00243                     type = 5;
00244             }
00245         }
00246 
00247         // Energy change (de = dE/E):
00248 
00249         real m1 = 1 - init.m2;
00250         real m2 = init.m2;
00251 
00252         real e_init = 0.5*m1*m2 / init.sma;
00253 
00254         if (final.escaper == 1)
00255             m1 = init.m3;
00256         else if (final.escaper == 2)
00257             m2 = init.m3;
00258         real e_final = 0.5*m1*m2 / final.sma;
00259 
00260         real de = e_final/e_init - 1;
00261 
00262         // Use logarithmic binning in dE/E (starting at DE_MIN).
00263 
00264         int je = -1;
00265         if (de >= DE_MIN)
00266             je = min(NE, (int) (EBINS_PER_DECADE * log10(de/DE_MIN)));
00267 
00268         // Use log_2 binning in final sma.
00269 
00270         int ja = (int) (ABINS_PER_DOUBLING * log2(final.sma/a_min));
00271 
00272         // Use linear binning in final ecc^2.
00273 
00274         int ke = (int) (NECC * final.ecc * final.ecc);
00275 
00276         // Update counters:
00277 
00278         if (type >= 0) {
00279             n_total[type][rho_zone]++;
00280             if (je >= 0) ne[je][type][rho_zone]++;
00281             if (ja >= 0 && ja < NSMA && ke >= 0 && ke < NECC)
00282                 nae[ja][ke][type][rho_zone]++;
00283         }
00284 
00285         // Diagnostics:
00286 /*
00287         int p = cerr.precision(STD_PRECISION);
00288         cerr << "accumulate_stats: " << state_string(inter.descriptor)
00289              << " " << state_string(final.descriptor)
00290              << ",  n_osc = " << inter.n_osc << endl;
00291         cerr << "  rho_zone = " << rho_zone;
00292         cerr << ",  je, ja, ke = " << je << "  " << ja << "  " << ke << endl;
00293         cerr << "  escaper = " << final.escaper;
00294         cerr << "  mass = " << final.system[final.escaper-1].mass;
00295         cerr << "  e_init = " << e_init;
00296         cerr << "  de/e = " << de << endl;
00297         cerr.precision(p);
00298 */
00299     }
00300 
00301     // Finally, check to see if any intermediate output is required.
00302 
00303     if (output_frequency >= 0) {
00304 
00305         total_trials[rho_zone]++;
00306         total_total++;
00307 
00308         if (total_total >= output_frequency) {
00309 
00310             // Check that all zones have the same number of trials.
00311 
00312             int kr;
00313             for (kr = 1; kr <= out.i_max; kr++)
00314                 if (total_trials[kr] != total_trials[0]) return;
00315 
00316             // Reset local counter and print cross-sections.
00317 
00318             total_total = 0;
00319 
00320             if (rho_zone != out.i_max)
00321                 cerr << "\naccumulate_stats:  Warning: not at end of row!\n";
00322 
00323             // We can only reach this point when we have just completed
00324             // a "row" of trials (so we should have rho_zone = out.i_max).
00325             // However, control will be transferred from the scatter driver
00326             // here *before* out.trials_per_zone is updated, so we must
00327             // temporarily do it here to make the intermediate cross
00328             // sections come out right.
00329 
00330             // NOTE: (1) The "trial density" is updated at a higher level
00331             //           within sigma3, so it will be wrong in these
00332             //           intermediate tables.
00333             //       (2) If we happen to get output just as the outer zone
00334             //           has been expanded and is being built up, the
00335             //           cross sections will be *wrong* (but counts are OK)
00336             //           because, in that rare case, trials_per_zone should
00337             //           not be incremented here...
00338 
00339             out.trials_per_zone++;      // <-----
00340 
00341             counts_to_sigma(out);
00342             print_sigma3(out, prof.v_inf * prof.v_inf);
00343             if (print_counts) print_all_sigma3_counts(out, cerr);
00344 
00345             // User-specific output:
00346 
00347             print_stats(prof, out);
00348 
00349             out.trials_per_zone--;      // <-----
00350 
00351         }       
00352     }
00353 }
00354 
00355 //----------------------------------------------------------------------
00356 //----------------------------------------------------------------------
00357 
00358 // No particular need to modify anything below this line.
00359 
00360 //----------------------------------------------------------------------
00361 //----------------------------------------------------------------------
00362 
00363 main(int argc, char **argv)
00364     {
00365     int  debug  = 1;
00366     int  seed   = 0;
00367     int  n_rand = 0;
00368     real max_trial_density = 1.0;
00369 
00370     real cpu_time_check = 3600; // One check per CPU hour!
00371     real dt_snap = VERY_LARGE_NUMBER;
00372     real snap_cube_size = 10;
00373     int scatter_summary_level = 0;
00374 
00375     scatter_profile prof;
00376     make_standard_profile(prof);
00377 
00378     extern char *poptarg;
00379     int c;
00380     char* param_string = "a:A:c:C:d:D:e:m:M:N:o:pqQs:v:V:x:y:z:";
00381 
00382     while ((c = pgetopt(argc, argv, param_string)) != -1)
00383         switch(c) {
00384 
00385             case 'a': a_min = atof(poptarg);
00386                       break;
00387             case 'A': prof.eta = atof(poptarg);
00388                       break;
00389             case 'c': cpu_time_check = 3600*atof(poptarg);// (Specify in hours)
00390                       break;
00391             case 'C': snap_cube_size = atof(poptarg);
00392                       break;
00393             case 'd': max_trial_density = atof(poptarg);
00394                       break;
00395             case 'D': dt_snap = atof(poptarg);
00396                       scatter_summary_level = 2;  // Undo with later "-q/Q"
00397                       break;
00398             case 'e': prof.ecc = atof(poptarg);
00399                       prof.ecc_flag = 1;
00400                       break;
00401             case 'm': prof.m2 = atof(poptarg);
00402                       break;
00403             case 'M': prof.m3 = atof(poptarg);
00404                       break;
00405             case 'N': n_rand = atoi(poptarg);
00406                       break;
00407             case 'o': output_frequency = atoi(poptarg);
00408                       break;
00409             case 'p': print_counts = 1 - print_counts;
00410                       break;
00411             case 'q': if (scatter_summary_level > 0)
00412                           scatter_summary_level = 0;
00413                       else
00414                           scatter_summary_level = 1;
00415                       break;
00416             case 'Q': if (scatter_summary_level > 0)
00417                           scatter_summary_level = 0;
00418                       else
00419                           scatter_summary_level = 2;
00420                       break;
00421             case 's': seed = atoi(poptarg);
00422                       break;
00423             case 'v': prof.v_inf = atof(poptarg);
00424                       break;
00425             case 'V': debug = atoi(poptarg);
00426                       break;
00427             case 'x': prof.r1 = atof(poptarg);
00428                       break;
00429             case 'y': prof.r2 = atof(poptarg);
00430                       break;
00431             case 'z': prof.r3 = atof(poptarg);
00432                       break;
00433             case '?': params_to_usage(cerr, argv[0], param_string);
00434                       exit(1);
00435         }
00436 
00437     // Debugging:    |debug| = 0 ==> no debugging output
00438     //               |debug| = 1 ==> output only at end (default)
00439     //               |debug| = 2 ==> output at end of each top-level iteration
00440     //               |debug| = 3 ==> output after each sub-trial
00441     //
00442     //                debug  < 0 ==> simple statistics also (default: off)
00443 
00444     cpu_init();
00445 
00446     sigma_out out;
00447     int first_seed = srandinter(seed, n_rand);
00448 
00449     cerr << "Random seed = " << first_seed << endl;
00450     print_profile(cerr, prof);
00451 
00452     initialize_stats();
00453 
00454     // Generic scattering experiment call, but an with additional hook to
00455     // transfer control to accumulate_stats (above) after each scattering.
00456 
00457     get_sigma3(max_trial_density, prof, out,
00458                debug, cpu_time_check,
00459                dt_snap, snap_cube_size,
00460                scatter_summary_level,
00461                accumulate_stats);
00462 
00463     // Out is the standard final descriptor of the scattering experiment.
00464     // It contains useful statistical and diagnostic information about
00465     // the details of what went on, but it may not be needed in all cases.
00466 
00467     // Standard "sigma3" output:
00468 
00469     print_sigma3(out, prof.v_inf * prof.v_inf);
00470     if (print_counts) print_all_sigma3_counts(out, cerr);
00471 
00472     // User-specific output:
00473 
00474     print_stats(prof, out);
00475 }

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