Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

sig_helper.C

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

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