Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

sig_helper3.C

Go to the documentation of this file.
00001 
00002 // sig_helper3.C: Engine for determining cross-sections in
00003 //                three-body scattering.
00004 
00005 // Differences from the previous version:
00006 //
00007 //      more streamlined scan over impact parameter
00008 //      decoupling of initialization, integration, and analysis functions
00009 //      parallel operation, eventually
00010 
00011 // Starlab library function.
00012 
00013 #include "sigma3.h"
00014 #include "pvm_scatt.h"
00015 
00016 // Pretty-print a scatter profile:
00017 
00018 void print_profile(ostream & s, scatter_profile & p, int prec)
00019 {
00020     int pp = s.precision(prec);
00021 
00022     s << "scatter_profile:" << endl
00023       << "   m1 = " << 1 - p.m2 << "  m2 = " << p.m2 << "  m3 = " << p.m3
00024       << "  r1 = " << p.r1 << "  r2 = " << p.r2 << "  r3 = " << p.r3;
00025 
00026     if (p.v_inf >= 0) s << "  v_inf = " << p.v_inf;
00027 
00028     s << endl;
00029 
00030     if (p.rho_flag)
00031         s << "   rho_min = " << p.rho_min
00032           << " rho_max = " << p.rho_max << endl;
00033 
00034     if (p.ecc_flag)
00035         s << "   binary_ecc = " << p.ecc << endl;
00036 
00037     if (p.phase_flag.cos_theta || p.phase_flag.phi || p.phase_flag.psi
00038          || p.phase_flag.mean_anomaly) {
00039 
00040         s << "  phase = ";
00041 
00042         if (p.phase_flag.cos_theta)
00043             s << acos(p.phase.cos_theta) << " ";
00044         else
00045             s << "- ";
00046 
00047         if (p.phase_flag.phi)
00048             s << p.phase.phi << " ";
00049         else
00050             s << "- ";
00051 
00052         if (p.phase_flag.psi)
00053             s << p.phase.psi << " ";
00054         else
00055             s << "- ";
00056 
00057         if (p.phase_flag.mean_anomaly)
00058             s << p.phase.mean_anomaly;
00059         else
00060             s << "-";
00061         
00062         s << endl;
00063         }
00064 
00065     s.precision(pp);
00066 }
00067 
00068 // Set up a template profile:
00069 
00070 void make_standard_profile(scatter_profile & prof)
00071 {
00072     prof.m2 = 0.5;
00073     prof.m3 = 0.5;
00074     prof.r1 = 0;
00075     prof.r2 = 0;
00076     prof.r3 = 0;
00077     prof.v_inf = 1;
00078     prof.tidal_tol_factor = DEFAULT_TIDAL_TOL_FACTOR;
00079     prof.rho_flag = 0;                                  // random impact par.
00080     prof.ecc_flag = 0;                                  // random eccentricity
00081     prof.phase_flag.cos_theta = 0;                      // random angles
00082     prof.phase_flag.phi = 0;
00083     prof.phase_flag.psi = 0;
00084     prof.phase_flag.mean_anomaly = 0;
00085     prof.ecc = 0;                                       // for definiteness
00086     prof.rho_min = 0;
00087     prof.rho_max = 0;
00088     prof.phase.cos_theta = 0;
00089     prof.phase.phi = 0;
00090     prof.phase.psi = 0;
00091     prof.phase.mean_anomaly = 0;
00092     prof.eta = DEFAULT_ETA;
00093     prof.intermediate_target = unknown_intermediate;
00094     prof.final_target1 = unknown_final;
00095     prof.final_target2 = unknown_final;
00096 }
00097 
00098 // Turn a scatter profile into a default initial state:
00099 
00100 void prof_to_init(scatter_profile & prof, initial_state3 & init)
00101 {
00102     if (prof.m2 > 1) {
00103         cerr << "prof_to_init: prof.m2 = " << prof.m2 << " > 1" << endl;
00104         exit(1);
00105     }
00106 
00107     make_standard_init(init);
00108 
00109     init.m2 = prof.m2;
00110     init.m3 = prof.m3;
00111     init.r1 = prof.r1;
00112     init.r2 = prof.r2;
00113     init.r3 = prof.r3;
00114     init.sma  = 1;
00115 
00116     // Maximum eccentricity to stay well away (by factor ECC_TOL) from contact:
00117 
00118     real ecc_max = 1 - ECC_TOL * (init.r1 + init.r2) / init.sma;
00119     if (ecc_max < 0)
00120         err_exit("prof_to_init: radii too large to initialize binary");
00121 
00122     init.v_inf = prof.v_inf;
00123 
00124     if (prof.rho_flag)
00125       init.rho = sqrt(randinter(prof.rho_min*prof.rho_min,
00126                                 prof.rho_max*prof.rho_max));
00127     else
00128       init.rho = 0;                       // The impact parameter rho will be
00129                                           // initialized elsewhere if random
00130     init.tidal_tol_factor = prof.tidal_tol_factor;
00131     init.eta = prof.eta;
00132 
00133     randomize_angles(init.phase);
00134     if (prof.phase_flag.mean_anomaly)
00135         init.phase.mean_anomaly = prof.phase.mean_anomaly;
00136     if (prof.phase_flag.cos_theta)
00137         init.phase.cos_theta = prof.phase.cos_theta;
00138     if (prof.phase_flag.phi) init.phase.phi = prof.phase.phi;
00139     if (prof.phase_flag.psi) init.phase.psi = prof.phase.psi;
00140 
00141     //  Initialize the eccentricity last for ease of programming in sigma3...
00142 
00143     if (prof.ecc_flag == 0) {
00144 
00145         // Thermal distribution of eccentricities in the allowed range.
00146 
00147         init.ecc = sqrt(randinter(0, ecc_max*ecc_max));
00148 
00149     } else if (prof.ecc_flag == 1) {
00150 
00151         // A particular eccentricity was specified.
00152 
00153         init.ecc = prof.ecc;
00154 
00155     } else if (prof.ecc_flag == 2) {
00156 
00157         // Bizarre observed eccentricity distribution (Mathieu)...
00158 
00159         init.ecc = -1;
00160         while (init.ecc < 0 || init.ecc > 1) init.ecc = gausrand(0.3, 0.15);
00161 
00162     } else
00163 
00164         err_exit("prof_to_init: illegal eccentricity flag");
00165 
00166 }
00167 
00168 int n_coll(int n_hits[N_INTER][N_FINAL][N_RHO_ZONE_MAX], int i_max)
00169 {
00170     int total = 0;      
00171 
00172     for (int i_int = 0; i_int < N_INTER; i_int++)
00173         for (int i_rho = 0; i_rho <= i_max; i_rho++)
00174             total += n_hits[i_int][merger_binary_1][i_rho]
00175                           + n_hits[i_int][merger_binary_2][i_rho]
00176                           + n_hits[i_int][merger_binary_3][i_rho]
00177                           + n_hits[i_int][merger_escape_1][i_rho]
00178                           + n_hits[i_int][merger_escape_2][i_rho]
00179                           + n_hits[i_int][merger_escape_3][i_rho]
00180                           + n_hits[i_int][triple_merger][i_rho];
00181     return total;
00182 }
00183 
00184 #define output_header_1 \
00185   "   pres   exch    ion merg_b merg_e merg_3  error   stop unknown\n"
00186 //     0      1       2     3      4      5      6      <-- n/s_total
00187 #define output_header_2 \
00188   "   pres   exch   ion  merg_b merg_e merg_3  error   stop\n"
00189 
00190 #define output_header_3 \
00191   "   pres  exch1  exch2    ion  error   stop\n"
00192 
00193 #define output_header_4 \
00194   "  mrg_b1 mrg_b2 mrg_b3 mrg_e1 mrg_e2 mrg_e3 3coll\n"
00195 
00196 static char *f_lab[] = {"non_res", "hier_res", "dem_res", "unknown"};
00197 // (static here to keep Sun CC happy...)
00198 
00199 // NOTE: All "print_sigma" functions start on the current line (i.e. they
00200 //       do not skip a line at the start) and skip a line at the end.
00201 
00202 char dummy_string[20];
00203 
00204 void print_sigma3_counts(int n_hits[N_INTER][N_FINAL][N_RHO_ZONE_MAX],
00205                          int i_max)
00206 {
00207     cerr << output_header_1;
00208 
00209     for (int i_int = 0; i_int < N_INTER; i_int++) {
00210 
00211         int n_total[N_FINAL - 5];
00212         for (int k = 0; k < N_FINAL - 5; k++) n_total[k] = 0;
00213 
00214         // Combine some categories:
00215 
00216         for (int i_rho = 0; i_rho <= i_max; i_rho++) {
00217             n_total[0] += n_hits[i_int][preservation][i_rho];
00218             n_total[1] += n_hits[i_int][exchange_1][i_rho]
00219                           + n_hits[i_int][exchange_2][i_rho];
00220             n_total[2] += n_hits[i_int][ionization][i_rho];
00221             n_total[3] += n_hits[i_int][merger_binary_1][i_rho]
00222                           + n_hits[i_int][merger_binary_2][i_rho]
00223                           + n_hits[i_int][merger_binary_3][i_rho];
00224             n_total[4] += n_hits[i_int][merger_escape_1][i_rho]
00225                           + n_hits[i_int][merger_escape_2][i_rho]
00226                           + n_hits[i_int][merger_escape_3][i_rho];
00227             n_total[5] += n_hits[i_int][triple_merger][i_rho];
00228             n_total[6] += n_hits[i_int][error][i_rho];
00229             n_total[7] += n_hits[i_int][stopped][i_rho];
00230             n_total[8] += n_hits[i_int][unknown_final][i_rho];
00231         }
00232 
00233         for (int i_fin = 0; i_fin < N_FINAL - 5; i_fin++) {
00234 
00235             cerr << " ";
00236 
00237             sprintf(dummy_string, "%d", n_total[i_fin]);
00238 
00239             // Use exactly 6 chars (+ 1 space) unless integer is very large.
00240 
00241             for (int i = 0; i < max(0, 6 - strlen(dummy_string)); i++)
00242                 cerr << " ";
00243             
00244             cerr << dummy_string;
00245         }
00246         cerr << "  " << f_lab[i_int] << endl;
00247     }
00248     cerr << endl;
00249 }
00250 
00251 local void print_formatted(real x)
00252 {
00253     cerr << " ";
00254 
00255     if ( (x < 1e6 && x > 0.01) || x <= 0) {
00256 
00257         sprintf(dummy_string, "%.3f", x);
00258 
00259         // Use exactly 7 characters unless integer is very large.
00260 
00261         for (int i = 0; i < max(1, 6 - strlen(dummy_string)); i++)
00262             cerr << " ";
00263 
00264         // Truncate the string, if x large (max = 999999).
00265 
00266         if (strlen(dummy_string) > 6) dummy_string[6] = '\0';
00267 
00268         cerr << dummy_string;
00269 
00270     } else if (x < 0.01)
00271         fprintf(stderr, "%7.1e", x);    // 2 sig. fig. for small numbers
00272     else
00273         fprintf(stderr, "%8.2e", x);    // 3 sig. fig. for large numbers
00274 }
00275 
00276 local void print_error(real x)
00277 {
00278     cerr << " ";
00279 
00280     if (x < 1) {
00281         if (x > 0.01 || x <= 0) {
00282             sprintf(dummy_string, "%.3f", x);
00283             fprintf(stderr, "+-%s", dummy_string+1);
00284         } else
00285             fprintf(stderr, "+-%5.0e", x);
00286     } else if (x < 10)
00287         fprintf(stderr, "+-%.2f", x);
00288     else
00289         fprintf(stderr, "+-%6.1e", x);
00290 }
00291 
00292 #define N_SIGMA3_ARR (N_FINAL - 6)
00293 
00294 void print_sigma3_array(real sigma[N_INTER][N_FINAL], real scale_factor,
00295                         int sqrt_flag)
00296 {
00297     cerr << output_header_2;
00298 
00299     for (int i_int = 0; i_int < N_INTER - 1; i_int++) {
00300 
00301         real s_total[N_SIGMA3_ARR];
00302 
00303         // Combine some categories (as in print_sigma3_counts):
00304 
00305         s_total[0] = sigma[i_int][preservation];
00306         s_total[1] = sigma[i_int][exchange_1]
00307                       + sigma[i_int][exchange_2];
00308         s_total[2] = sigma[i_int][ionization];
00309         s_total[3] = sigma[i_int][merger_binary_1]
00310                       + sigma[i_int][merger_binary_2]
00311                       + sigma[i_int][merger_binary_3];
00312         s_total[4] = sigma[i_int][merger_escape_1]
00313                       + sigma[i_int][merger_escape_2]
00314                       + sigma[i_int][merger_escape_3];
00315         s_total[5] = sigma[i_int][triple_merger];
00316         s_total[6] = sigma[i_int][error];
00317         s_total[7] = sigma[i_int][stopped];
00318 
00319         for (int i_fin = 0; i_fin < N_SIGMA3_ARR; i_fin++) {
00320             if (i_int == 0 && i_fin == 0) 
00321                 fprintf(stderr, "       ");
00322             else {
00323                 real temp = (sqrt_flag == 0 ? s_total[i_fin]
00324                                             : sqrt(s_total[i_fin]));
00325                 print_formatted(scale_factor * temp);
00326             }
00327         }
00328         cerr << "         " << f_lab[i_int] << endl;
00329     }
00330     cerr << endl;
00331 }
00332 
00333 // print_sigma3_err_array: print errors, assuming that SQUARES are sent.
00334 
00335 void print_sigma3_err_array(real sigma_err_sq[N_INTER][N_FINAL],
00336                             real scale_factor)
00337 {
00338     print_sigma3_array(sigma_err_sq, scale_factor, 1);
00339 }
00340 
00341 #define N_SIGMA3_NM_ARR (N_FINAL - 1)
00342 
00343 void print_sigma3_nonmergers(real sigma[N_INTER][N_FINAL],
00344                              real sigma_err_sq[N_INTER][N_FINAL],
00345                              real v2)
00346 {
00347     cerr << output_header_3 << endl; 
00348 
00349     for (int i_int = 0; i_int < N_INTER - 1; i_int++) {
00350 
00351         // Cross-sections:
00352 
00353         for (int i_fin = 0; i_fin <  N_SIGMA3_NM_ARR; i_fin++) {
00354             if (i_int == 0 && i_fin == 0) 
00355                 fprintf(stderr, "       ");
00356             else if (i_fin <= 3 || i_fin >=  N_SIGMA3_NM_ARR - 2)
00357                 print_formatted(v2 * sigma[i_int][i_fin]);
00358         }
00359         cerr << "                       " << f_lab[i_int] << endl;
00360 
00361         // Errors:
00362 
00363         for (int i_fin = 0; i_fin <  N_SIGMA3_NM_ARR; i_fin++) {
00364             if (i_int == 0 && i_fin == 0) 
00365                 fprintf(stderr, "       ");
00366             else if (i_fin <= 3 || i_fin >=  N_SIGMA3_NM_ARR - 2)
00367                 print_error(v2 * sqrt(sigma_err_sq[i_int][i_fin]));
00368         }
00369         cerr << "\n\n";
00370     }
00371 }
00372 
00373 void print_sigma3_mergers(real sigma[N_INTER][N_FINAL],
00374                           real sigma_err_sq[N_INTER][N_FINAL],
00375                           real v2)
00376 {
00377     cerr << output_header_4 << endl;
00378 
00379     for (int i_int = 0; i_int < N_INTER - 1; i_int++) {
00380 
00381         // Cross-sections:
00382             
00383         for (int i_fin = 4; i_fin < 11; i_fin++) {
00384             if (i_int == 0 && i_fin == 0) 
00385                 fprintf(stderr, "       ");
00386             else
00387                 print_formatted(v2 * sigma[i_int][i_fin]);
00388         }
00389         cerr << "                " << f_lab[i_int] << endl;
00390             
00391         // Errors:
00392             
00393         for (int i_fin = 4; i_fin < 11; i_fin++) {
00394             if (i_int == 0 && i_fin == 0) 
00395                 fprintf(stderr, "       ");
00396             else
00397                 print_error(v2 * sqrt(sigma_err_sq[i_int][i_fin]));
00398         }
00399         cerr << "\n\n";
00400     }
00401 }
00402 
00403 local void create_temp(char* temp, int length, char* string)
00404 {
00405     for (int k = 0; k < length; k++) temp[k] = ' ';
00406     strcpy(temp, string);
00407     for (int k = 0; k < length; k++) if (temp[k] == '\0') temp[k] = ' ';
00408     temp[length-1] = '\0';
00409 }
00410 
00411 void print_sigma3(sigma_out & out, real v2)
00412 {
00413     int i;
00414 
00415     cerr << endl;
00416     for (i = 0; i < 72; i++) cerr << "-";
00417     cerr << endl;
00418 
00419     int p = cerr.precision(STD_PRECISION);
00420     cerr << "\n   rho_max = " << out.rho_max
00421          << "  i_max = " << out.i_max << endl;
00422     cerr << "   central_trial_density = " << out.central_trial_density
00423          << "  total_trials = " << out.total_trials << endl;
00424 
00425     cerr << "   average steps = " << out.total_steps / (real) out.total_trials
00426          << "  maximum = " << out.max_steps << endl;
00427     cerr << "   timesteps    (bin factor = 10): ";
00428     for (i = 0; i < N_STEP_BIN; i++) cerr << " " << out.step_counter[i];
00429     cerr << endl;
00430 
00431     int coll_total = n_coll(out.n_hits, out.i_max);
00432 
00433     cerr << "   oscillations (bin factor =  2):" << endl;
00434     int jmax = (int)triple_merger;
00435     if (coll_total == 0) jmax = (int)ionization;
00436 
00437 #   define N_TEMP   36
00438 #   define N_INDENT 17
00439 
00440     char temp[N_TEMP];
00441     for (int k = 0; k < N_TEMP; k++) temp[k] = ' ';
00442 
00443     for (int j = 0; j <= jmax; j++) {
00444         create_temp(temp + N_INDENT, N_TEMP - N_INDENT,
00445                     state_string((final_descriptor3)j));
00446         cerr << temp;
00447         for (i = 0; i < N_OSC_BIN; i++) cerr << " " << out.osc_counter[i][j];
00448         cerr << endl;
00449     }
00450 
00451     create_temp(temp + N_INDENT, N_TEMP - N_INDENT, "total");
00452     cerr << temp;
00453 
00454     int osc_total[N_OSC_BIN];
00455     for (i = 0; i < N_OSC_BIN; i++) osc_total[i] = 0;
00456     for (int j = 0; j <= jmax; j++)
00457         for (i = 0; i < N_OSC_BIN; i++) osc_total[i] += out.osc_counter[i][j];
00458     for (i = 0; i < N_OSC_BIN; i++) cerr << " " << osc_total[i];
00459     cerr << endl;
00460 
00461     // Raw counts:
00462 
00463     cerr << endl << "raw counts:\n\n";
00464     print_sigma3_counts(out.n_hits, out.i_max);
00465 
00466     // Cross-sections:
00467 
00468     cerr << "v^2 sigma / (pi a^2):\n\n";
00469     print_sigma3_array(out.sigma, v2);
00470 
00471     // More detail and errors:
00472 
00473     // Non-mergers first (0-3, N_FINAL-2):
00474 
00475     print_sigma3_nonmergers(out.sigma, out.sigma_err_sq, v2);
00476 
00477     // Then mergers (4-10):
00478 
00479     if (coll_total > 0) 
00480         print_sigma3_mergers(out.sigma, out.sigma_err_sq, v2);
00481 
00482     cerr << flush;
00483     cerr.precision(p);
00484 }
00485 
00486 // print_counts: print out enough information to determine cross-sections
00487 //               and errors, and to combine them with other runs.
00488 
00489 void print_all_sigma3_counts(sigma_out & out, ostream & s)
00490 {
00491     int p = s.precision(STD_PRECISION);
00492     s << "Counts:"
00493          << "\n  i_max = " << out.i_max
00494          << "  trials_per_zone = " << out.trials_per_zone
00495          << "\n  rho_sq_init = " << out.rho_sq_init
00496          << "  RHO_SQ_FACTOR = " << RHO_SQ_FACTOR << endl;
00497 
00498     for (int i_int = 0; i_int < N_INTER; i_int++)
00499         for (int i_fin = 0; i_fin < N_FINAL; i_fin++)
00500             for (int i_rho = 0; i_rho <= out.i_max; i_rho++)
00501                 s << out.n_hits[i_int][i_fin][i_rho] << " ";
00502     s << endl;
00503     cerr.precision(p);
00504 } 
00505 
00506 //------------------------------------------------------------------------
00507 
00508 // Encapsulate the following functions -- efficiency is not an issue here.
00509 
00510 real zone_area(sigma_out& out, int i)   // (without the PI)
00511 {
00512     real rho_sq_min = 0, rho_sq_max;
00513 
00514     rho_sq_max = out.rho_sq_init * pow(RHO_SQ_FACTOR, i);
00515     if (i > 0) rho_sq_min = rho_sq_max / RHO_SQ_FACTOR;
00516 
00517     return rho_sq_max - rho_sq_min;
00518 }
00519 
00520 real zone_density(sigma_out& out, int i)
00521 {
00522     return out.trials_per_zone / zone_area(out, i);
00523 }
00524 
00525 real zone_weight(sigma_out& out, int i)
00526 {
00527     return zone_area(out, i) / out.trials_per_zone;
00528 }
00529 
00530 //------------------------------------------------------------------------
00531 
00532 // counts_to_sigma: Convert raw counts into cross-sections and errors.
00533 //                  This will update sigma from the current counts,
00534 //                  making NO other changes in the sigma_out structure.
00535 
00536 void counts_to_sigma(sigma_out & out)
00537 {
00538     out.sigma_total = 0;
00539     out.sigma_total_err_sq = 0;
00540 
00541     for (int i_int = 0; i_int < N_INTER; i_int++)
00542         for (int i_fin = 0; i_fin < N_FINAL; i_fin++) {
00543 
00544             out.sigma[i_int][i_fin] = 0;
00545             out.sigma_err_sq[i_int][i_fin] = 0;
00546 
00547             for (int i_rho = 0; i_rho <= out.i_max; i_rho++) {
00548 
00549 //              if (out.n_hits[i_int][i_fin][i_rho] > 0)
00550 //                  cerr<<"i_int = "<<i_int<<" i_fin = "<<i_fin
00551 //                      <<" i_rho = "<<i_rho<<" "
00552 //                      <<out.n_hits[i_int][i_fin][i_rho]<<endl;
00553 
00554                 real weight = zone_weight(out, i_rho);
00555 
00556                 real delta_sigma =  weight * out.n_hits[i_int][i_fin][i_rho];
00557                 real delta_err_sq = weight * weight
00558                                      * out.n_hits[i_int][i_fin][i_rho];
00559 
00560                 out.sigma[i_int][i_fin] += delta_sigma;
00561                 out.sigma_err_sq[i_int][i_fin] += delta_err_sq;
00562 
00563                 if (i_int > 0 || i_fin > 0) {
00564                     out.sigma_total += delta_sigma;
00565                     out.sigma_total_err_sq += delta_err_sq;
00566                 }
00567             }
00568         }
00569 } 
00570 
00571 // Elementary statistics:
00572 
00573 real max_t = 0;                                        // global variables!!
00574 real max_err = 0;
00575 
00576 local void print_status(real v_inf, sigma_out & out, int debug)
00577 {
00578     int p = cerr.precision(STD_PRECISION);
00579     cerr.setf(ios::fixed, ios::floatfield);
00580      
00581     counts_to_sigma(out);
00582  
00583     cerr << "sigma[" << v_inf << "] = " << out.sigma_total
00584          << " +/- " << sqrt(out.sigma_total_err_sq)
00585          << "  v^2 sigma = " << out.sigma_total*v_inf*v_inf
00586          << " +/- " << sqrt(out.sigma_total_err_sq)*v_inf*v_inf
00587          << endl;
00588  
00589     if (debug < 0)
00590         cerr << "  n_total = "  << out.total_trials
00591              << "  max_t = "    << max_t
00592              << "  max_err = "  << max_err
00593              << "  n_hit_tot = "<< out.n_hit_tot
00594              << endl;
00595 
00596     cerr.precision(p);
00597 }
00598 
00599 // summarize_scattering_initial: Print a line specifying a
00600 //                               scattering experiment.
00601 
00602 void summarize_scattering_initial(initial_state3 & init,
00603                                   int n_rand,
00604                                   real dt_snap,
00605                                   real snap_cube_size)
00606 {
00607     int p = cerr.precision(STD_PRECISION);
00608 
00609     cerr << "\nscatter3"
00610          << " -s " << get_initial_seed()
00611          << " -N " << n_rand;
00612 
00613     cerr.precision(16);                         // Uglify the output
00614     cerr << " -m " << init.m2
00615          << " -M " << init.m3
00616          << " -v " << init.v_inf
00617          << " -e " << init.ecc
00618          << " -r " << init.rho
00619          << " -x " << init.r1
00620          << " -y " << init.r2
00621          << " -z " << init.r3
00622          << " -A " << init.eta
00623          << " -g " << init.tidal_tol_factor;
00624 
00625     cerr.precision(STD_PRECISION);
00626     if (dt_snap < VERY_LARGE_NUMBER) {
00627         cerr << " -D " << dt_snap
00628              << " -C " << snap_cube_size;
00629     }
00630 
00631     cerr << endl;
00632 
00633     // print_initial(cerr, init);
00634 
00635     cerr.precision(p);
00636 }
00637 
00638 // summarize_scattering_final: Print a line specifying a scattering result.
00639 
00640 void summarize_scattering_final(intermediate_state3 & inter,
00641                                 final_state3 & final,
00642                                 int level,
00643                                 real cpu)
00644 {
00645     cerr << "outcome:  ";
00646     print_scatter3_outcome(inter, final, cerr);
00647 
00648     if (level > 1) print_scatter3_summary(inter, final, cpu, cerr);
00649 
00650 //    print_final(cerr, final);
00651 }
00652 
00653 //=========================================================================
00654 //
00655 // Functions to initialize, perform, and analyze a scattering experiment.
00656 //
00657 //=========================================================================
00658 
00659 // single_scatter_init: Initialize a scattering experiment in the specified
00660 //                      rho range with the given v_inf.
00661 
00662 void single_scatter_init(scatter_profile & prof,
00663                          real rho_sq_min, real rho_sq_max,
00664                          initial_state3 & init, int & n_rand,
00665                          int scatter_summary, real dt_snap, real snap_cube_size)
00666 {
00667     n_rand = get_n_rand();
00668 
00669     // Initialize the scattering experiment:
00670 
00671     prof_to_init(prof, init);
00672 
00673     // Choose rho randomly from the allowed range:
00674 
00675     if (prof.rho_flag == 0)
00676         init.rho = sqrt(randinter(rho_sq_min, rho_sq_max));
00677     else
00678         init.rho = rho_sq_min;
00679 
00680     if (scatter_summary > 0)
00681         summarize_scattering_initial(init, n_rand, dt_snap, snap_cube_size);
00682 
00683 }
00684 
00685 // single_scatter: Perform a scattering experiment with the specified init.
00686 
00687 int single_scatter(initial_state3 & init,
00688                    intermediate_state3 & inter,
00689                    final_state3 & final,
00690                    real cpu_time_check,
00691                    real dt_snap,
00692                    real snap_cube_size)
00693 {
00694     // Perform a scattering experiment with the specified init, returning
00695     // result = false if the outcome is a non-resonant preservation.
00696 
00697     scatter3(init, inter, final, cpu_time_check,
00698              VERY_LARGE_NUMBER, dt_snap, snap_cube_size);
00699 
00700     // Return a "hit" if the result was
00701     //
00702     //          (1) not a flyby (preservation non_resonance)
00703     //          (2) not an error, stopped, or unknown_final.
00704     //
00705     // Modify this return statement to change the definition of a "hit".
00706     // Probably should take into account the size of the perturbation?
00707 
00708     return (final.descriptor == error
00709             || final.descriptor == stopped
00710             || final.descriptor == unknown_final
00711             || (final.descriptor == preservation
00712                 && inter.descriptor == non_resonance) ? 0 : 1);
00713 }
00714 
00715 // single_scatter_stats: Accumulate information on scattering outcomes.
00716 
00717 void single_scatter_stats(scatter_profile & prof,
00718                           initial_state3 & init,
00719                           intermediate_state3 & inter,
00720                           final_state3 & final,
00721                           int rho_bin_index,
00722                           sigma_out & out,
00723                           stat_fp acc_stats,
00724                           int result)
00725 {
00726     // Accumulate statistics:
00727 
00728     max_t = max(max_t, final.time);
00729     max_err = max(max_err, abs(final.error));
00730 
00731     // Accumulate results on data not available to higher levels:
00732 
00733     out.n_hits[inter.descriptor][final.descriptor][rho_bin_index]++;
00734 
00735     out.total_steps += final.n_steps;
00736     out.max_steps = max(out.max_steps, final.n_steps);
00737     real logn = log10((real)max(1, final.n_steps));
00738     int index = min(N_STEP_BIN-1, (int)logn);
00739     out.step_counter[index]++;
00740 
00741     logn = log10((real)max(1, inter.n_osc)) / log10(2.0);
00742     index = min(N_OSC_BIN-1, (int)logn);
00743     out.osc_counter[index][final.descriptor]++;
00744 
00745     // Convenient to update these global counters here also:
00746 
00747     out.total_trials++;
00748     out.n_hit[rho_bin_index] += result;
00749     out.n_hit_tot += result;
00750 
00751     //------------------------------------------------------------------
00752     // Optional call to user-supplied function for more detailed
00753     // statistics gathering. The function must maintain its own internal
00754     // data in a way that can be extracted later.
00755     //------------------------------------------------------------------
00756 
00757     if (acc_stats)
00758         (*acc_stats)(prof, init, inter, final, rho_bin_index, out);
00759 }
00760 
00761 //=========================================================================
00762 
00763 // get_sigma3: Run three-body scatterings for a given velocity at infinity
00764 //             and return cross-sections for all possible outcomes.
00765 //             Stop when the specified trial density is exceeded.
00766 //
00767 //             The trials are performed by function "trial" and debugging
00768 //             information is printed out by the function "print".
00769 //
00770 // In addition to determining cross-sections, get_sigma3 may also be used
00771 // as a convenient means of driving a more specialized function acc_stats,
00772 // which can gather additional statistics.  Get_sigma3 guarantees that the
00773 // data sent to acc_stats are properly sampled over impact parameter space.
00774 
00775 void get_sigma3(real max_trial_density, // "density" of trials
00776                 scatter_profile & prof, // profile describing the run
00777                 sigma_out & out,        // outcome structure
00778                 int debug,              // output control
00779                 real cpu_time_check,    // interval to print CPU time
00780                 real dt_snap,           // snapshot output interval
00781                 real snap_cube_size,    // size of snap cube
00782                 int scatter_summary_flag,// output on each scattering
00783                 stat_fp acc_stats,      // optional function to accumulate
00784                                         //     statistics on the runs
00785                 print_fp print)         // function to print system
00786                                         //     status
00787 {
00788     if (prof.rho_flag)                  // Impact parameter has been specified.
00789         err_exit("get_sigma3: prof.rho_flag has been set!");
00790 
00791     // (This routine is intended for calculation of the cross-section
00792     // without restrictions on the impact parameter)
00793 
00794     if (prof.v_inf <= 0)
00795         err_exit("get_sigma3: sigma undefined for parabolic orbits");
00796 
00797     if (prof.r1 + prof.r2 >= 1)
00798         err_exit("get_sigma3: contact binary");
00799 
00800     // Initialize counters.
00801 
00802     int i_int, i_fin, rho_zone;
00803 
00804     for (i_int = 0; i_int < N_INTER; i_int++)
00805         for (i_fin = 0; i_fin < N_FINAL; i_fin++)
00806             for (rho_zone = 0; rho_zone < N_RHO_ZONE_MAX; rho_zone++)
00807             out.n_hits[i_int][i_fin][rho_zone] = 0;
00808 
00809     out.total_trials = 0;
00810     out.n_hit_tot = 0;
00811     for (rho_zone = 0; rho_zone < N_RHO_ZONE_MAX; rho_zone++)
00812         out.n_hit[rho_zone] = 0;
00813     
00814     out.max_steps = 0;
00815     out.total_steps = 0;
00816     for (int i = 0; i < N_STEP_BIN; i++) out.step_counter[i] = 0;
00817 
00818     for (int i = 0; i < N_OSC_BIN;  i++)
00819         for (int j = 0; j < N_FINAL; j++)
00820             out.osc_counter[i][j] = 0;
00821 
00822     real cpu_init = cpu_time(); // The CPU time when we entered get_sigma3
00823     real cpu_save = cpu_init;
00824 
00825     int scatt_total = 0;        // Maintain these for use in parallel case
00826     real cpu_total = 0;
00827 
00828     out.i_max = 1;  // i value of safety bin, to be sampled, but supposed
00829                     // to contain no events, i.e. rho bins run from 0 to 
00830                     // i_max, with i_max empty
00831 
00832     // Take gravitational focusing into account in the allowed range
00833     // of rho squared.
00834 
00835     real v_sq = prof.v_inf * prof.v_inf;
00836     out.rho_sq_init = RHO_SQ_SCALE * (1 + 2 * (1 + prof.m3) / v_sq);
00837 
00838     // We normalize the density of trials by requiring a given number of
00839     // trials in an effective  pericenter target area, i.e. a typical area
00840     // of interest, measured in "pericenter" units (rho units with 
00841     // gravitational focusing scaling taken out) within which interesting
00842     // results are expected.
00843     //
00844     // For hard binaries (v_inf --> 0), we just take the geometrical area of 
00845     // the binary, since any encounter within this pericenter area is likely
00846     // to do something interesting.
00847     //
00848     // For soft binaries (v_inf --> infinity), we must take a smaller area,
00849     // by a factor 1/v_sq, since in the impulse approximation the same momentum
00850     // transfer at higher energy requires a closer encounter by a factor of
00851     // 1/v_inf.  Thus, the effective density is reduced by a factor 1/v_sq.
00852 
00853     real pericenter_target_factor = 1 / (1 + v_sq);
00854 
00855     out.trials_per_zone = (int) (max_trial_density * RHO_SQ_SCALE
00856                                   / pericenter_target_factor + 0.5);
00857     out.central_trial_density = (out.trials_per_zone / RHO_SQ_SCALE)
00858                                         * pericenter_target_factor;
00859 
00860     // Some useful diagnostic feedback (before the fact):
00861 
00862     if (debug != 0) cerr << "==========\n";
00863     else cerr << endl;
00864 
00865     cerr << "get_sigma3:  v_inf = " << prof.v_inf
00866          << ",  trials_per_zone = " << out.trials_per_zone << endl;
00867 
00868     real rho_sq_min, rho_sq_max;
00869 
00870     initialize_processors(out.trials_per_zone, debug);  // PVM or dummy call
00871 
00872     for (rho_zone = 0, rho_sq_min = 0, rho_sq_max = out.rho_sq_init;
00873          rho_zone <= out.i_max;
00874          rho_zone++, rho_sq_min = rho_sq_max, rho_sq_max *= RHO_SQ_FACTOR) {
00875 
00876         // Perform out.trials_per_zone scatterings in each annulus,
00877         // and keep track of the results.
00878 
00879         int result = multiscatter3(prof, out,
00880                                    rho_sq_min, rho_sq_max, rho_zone,
00881                                    dt_snap, snap_cube_size,
00882                                    cpu_time_check, cpu_init, cpu_save,
00883                                    scatt_total, cpu_total, acc_stats,
00884                                    debug, scatter_summary_flag);
00885 
00886         if (debug)
00887             cerr << "rho_zone = " << rho_zone << ",  result = " << result;
00888 
00889         if (rho_zone == out.i_max && result > 0) out.i_max++;
00890 
00891         if (debug)
00892             cerr << ",  out.i_max = " << out.i_max << endl;
00893 
00894     }
00895 
00896     cerr << "\ntotal scatterings = " << scatt_total
00897          << ",  CPU time = " << cpu_total << endl;
00898 
00899     terminate_processors(debug);        // PVM or dummy call
00900 
00901     if (abs(debug) == 1) (*print)(prof.v_inf, out, debug);
00902 
00903     out.rho_max = sqrt(rho_sq_max);
00904     counts_to_sigma(out);
00905 }
00906 
00907 //=========================================================================
00908 
00909 // Establish versions of get_sigma3 with specific defaults, using the
00910 // print_status routine provided in this file.
00911 
00912 // NOTE: This version fixes the use of the old "single_scatter" as
00913 //       the basic scattering function.
00914 
00915 // Add DEFAULT print_status and NULL acc_stats:
00916 
00917 void get_sigma3(real max_trial_density,
00918                 scatter_profile & prof,
00919                 sigma_out & out,
00920                 int debug,
00921                 real cpu_time_check,
00922                 real dt_snap,
00923                 real snap_cube_size,
00924                 int scatter_summary_flag)
00925 {
00926     get_sigma3(max_trial_density, prof, out, debug, cpu_time_check,
00927                dt_snap, snap_cube_size, scatter_summary_flag,
00928                (stat_fp) NULL,
00929                print_status);
00930 }
00931 
00932 // Add DEFAULT print_status to SPECIFIED acc_stats:
00933 
00934 void get_sigma3(real max_trial_density,
00935                 scatter_profile & prof,
00936                 sigma_out & out,
00937                 int debug,
00938                 real cpu_time_check,
00939                 real dt_snap,
00940                 real snap_cube_size,
00941                 int scatter_summary_flag,
00942                 stat_fp acc_stats)
00943 {
00944     get_sigma3(max_trial_density, prof, out, debug, cpu_time_check,
00945                dt_snap, snap_cube_size, scatter_summary_flag,
00946                acc_stats,
00947                print_status);
00948 }
00949 
00950 
00951 // Add NULL acc_stats to SPECIFIED print_status:
00952 
00953 void get_sigma3(real max_trial_density,
00954                 scatter_profile & prof,
00955                 sigma_out & out,
00956                 int debug,
00957                 real cpu_time_check,
00958                 real dt_snap,
00959                 real snap_cube_size,
00960                 int scatter_summary_flag,
00961                 print_fp print)
00962 {
00963     get_sigma3(max_trial_density, prof, out, debug, cpu_time_check,
00964                dt_snap, snap_cube_size, scatter_summary_flag,
00965                (stat_fp) NULL,
00966                print);
00967 }

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