00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "hdyn.h"
00024 #include "star/dstar_to_kira.h"
00025
00026 typedef struct {
00027 real dt;
00028 real dt_a;
00029 hdyn* b;
00030 } dt_pair, *dt_pair_ptr;
00031
00032 local int compare_dt(const void * pi, const void * pj)
00033 {
00034 if (((dt_pair_ptr) pi)->dt < ((dt_pair_ptr) pj)->dt)
00035 return -1;
00036 else if (((dt_pair_ptr)pi)->dt > ((dt_pair_ptr)pj)->dt)
00037 return +1;
00038 else
00039 return 0;
00040 }
00041
00042 typedef struct {
00043 real count;
00044 hdyn* b;
00045 } count_pair, *count_pair_ptr;
00046
00047 local int compare_steps(const void * pi, const void * pj)
00048 {
00049 if (((count_pair_ptr) pi)->count > ((count_pair_ptr) pj)->count)
00050 return -1;
00051 else if (((count_pair_ptr)pi)->count < ((count_pair_ptr)pj)->count)
00052 return +1;
00053 else
00054 return 0;
00055 }
00056
00057 int get_effective_block(real dt)
00058 {
00059
00060
00061
00062
00063
00064
00065
00066 int k = 0;
00067 real dtb = 1;
00068
00069 while (fmod(dt, dtb) != 0 && k < 50) {
00070 k++;
00071 dtb /= 2;
00072 }
00073
00074 return k;
00075 }
00076
00077 #define NTOP 10
00078 #define NBOT 10
00079
00080 local void print_timestep_stats(hdyn* b)
00081 {
00082
00083
00084 real dt_mean = 0, dt_min = VERY_LARGE_NUMBER, dt_max = -dt_min;
00085
00086 real n_dt = 0;
00087 real n_dt_p = 0;
00088 real n_dt_u = 0;
00089 real total_steps = 0;
00090 real total_steps_a = 0;
00091 real total_steps_p = 0;
00092
00093
00094
00095 int count[30],
00096 count_a[30],
00097 count_p[30],
00098 count_u[30],
00099 count_ue[30],
00100 count_next[30];
00101
00102 int i;
00103 for (i = 0; i < 30; i++)
00104 count[i] = count_a[i]
00105 = count_p[i]
00106 = count_u[i]
00107 = count_ue[i]
00108 = count_next[i]
00109 = 0;
00110
00111
00112
00113 int n = 0;
00114 for_all_nodes(hdyn, b, bb) n++;
00115 n--;
00116
00117 dt_pair_ptr list_dt = new dt_pair[n];
00118 dt_pair_ptr list_dtb = new dt_pair[n];
00119
00120
00121
00122 count_pair_ptr steps_inst = new count_pair[n];
00123 count_pair_ptr steps_delta = new count_pair[n];
00124 count_pair_ptr f_dir_delta = new count_pair[n];
00125 count_pair_ptr f_ind_delta = new count_pair[n];
00126
00127 n = 0;
00128 int np = 0, nd = 0, ni = 0;
00129
00130 real delta_steps_tot = 0;
00131 real delta_f_dir_tot = 0;
00132 real delta_f_ind_tot = 0;
00133
00134 bool print_dtb = false;
00135
00136 for_all_nodes(hdyn, b, bb)
00137 if (bb != b) {
00138
00139 real dt = bb->get_timestep();
00140
00141
00142
00143
00144
00145
00146 real dt_a = dt;
00147 if (bb->get_kepler())
00148 dt_a = bb->get_unperturbed_timestep();
00149
00150
00151
00152 if (bb->is_top_level_node() || bb->get_elder_sister() == NULL) {
00153
00154
00155
00156 dt_mean += dt_a;
00157 dt_min = min(dt_min, dt_a);
00158 dt_max = max(dt_max, dt_a);
00159
00160 n_dt += 1;
00161 real steps = rint(1/dt);
00162 real steps_a = rint(1/dt_a);
00163 total_steps += steps;
00164 total_steps_a += steps_a;
00165
00166
00167
00168 if (!bb->get_kepler()) {
00169
00170 list_dt[np].dt = dt;
00171 list_dt[np].dt_a = dt;
00172 list_dt[np].b = bb;
00173 steps_inst[np].count = steps;
00174 steps_inst[np].b = bb;
00175 np++;
00176 }
00177
00178
00179
00180
00181 i = 0;
00182 real dtbin = 1;
00183 while (dt < dtbin) {
00184 i++;
00185 dtbin *= 0.5;
00186 }
00187 if (i > 29) i = 29;
00188 count[i]++;
00189
00190 if (!bb->get_kepler()) {
00191
00192
00193
00194 total_steps_p += steps;
00195 n_dt_p += 1;
00196 count_p[i]++;
00197
00198 }
00199
00200
00201
00202
00203 i = 0;
00204 dtbin = 1;
00205 while (dt_a < dtbin) {
00206 i++;
00207 dtbin *= 0.5;
00208 }
00209 if (i > 29) i = 29;
00210 count_a[i]++;
00211
00212 if (bb->get_kepler()) {
00213
00214
00215
00216 n_dt_u += 1;
00217 count_u[i]++;
00218
00219
00220
00221 int kb = get_effective_block(dt_a);
00222 if (kb > 29) kb = 29;
00223 count_ue[kb]++;
00224 }
00225
00226
00227
00228 real dt_next = bb->get_next_time() - bb->get_system_time();
00229 int kb = get_effective_block(dt_next);
00230 real dtb = pow(2.0, -kb);
00231
00232 list_dtb[n].dt = -kb;
00233 list_dtb[n].dt_a = dt_a;
00234 list_dtb[n].b = bb;
00235
00236 if (bb->get_kepler() || dt_a != dtb) {
00237
00238 if (!print_dtb) {
00239 cerr << endl << " Actual and block timesteps:"
00240 << endl;
00241 print_dtb = true;
00242 }
00243
00244 if (bb->get_kepler())
00245 cerr << " unperturbed ";
00246 else
00247 cerr << " ***mismatch ";
00248
00249 cerr << bb->format_label() << ": ";
00250 PRC(kb), PRC(dt_a); PRL(dtb);
00251 }
00252
00253 if (kb > 29) kb = 29;
00254 count_next[kb]++;
00255
00256
00257
00258
00259
00260 steps_delta[n].count = bb->get_steps();
00261 if (find_qmatch(bb->get_dyn_story(), "prev_steps"))
00262 steps_delta[n].count -= getrq(bb->get_dyn_story(),
00263 "prev_steps");
00264 putrq(bb->get_dyn_story(), "prev_steps", bb->get_steps());
00265 steps_delta[n].b = bb;
00266 delta_steps_tot += steps_delta[n].count;
00267
00268 n++;
00269
00270
00271
00272 f_dir_delta[nd].count = bb->get_direct_force();
00273 if (find_qmatch(bb->get_dyn_story(), "prev_f_dir"))
00274 f_dir_delta[nd].count -= getrq(bb->get_dyn_story(),
00275 "prev_f_dir");
00276 putrq(bb->get_dyn_story(), "prev_f_dir",
00277 bb->get_direct_force());
00278 f_dir_delta[nd].b = bb;
00279 delta_f_dir_tot += f_dir_delta[nd].count;
00280 nd++;
00281
00282
00283
00284 f_ind_delta[ni].count = bb->get_indirect_force();
00285 if (find_qmatch(bb->get_dyn_story(), "prev_f_ind"))
00286 f_ind_delta[ni].count -= getrq(bb->get_dyn_story(),
00287 "prev_f_ind");
00288 putrq(bb->get_dyn_story(), "prev_f_ind",
00289 bb->get_indirect_force());
00290 f_ind_delta[ni].b = bb;
00291 delta_f_ind_tot += f_ind_delta[ni].count;
00292 ni++;
00293 }
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303 cerr << endl << " Timesteps (younger binary components excluded,"
00304 << endl << " mean = " << dt_mean/max((int)rint(n_dt), 1)
00305 << " min = " << dt_min << " max = " << dt_max << "):"
00306 << endl;
00307
00308 if (n_dt_u > 0)
00309 cerr << endl << " all nodes (perturbed steps, bin #1 = 1, dt /= 2):"
00310 << endl << " ";
00311 else
00312 cerr << endl << " all nodes (actual steps, bin #1 = 1, dt /= 2):"
00313 << endl << " ";
00314
00315 for (i = 0; i < 10; i++) fprintf(stderr, " %5d", count[i]);
00316 cerr << endl << " ";
00317 for (i = 10; i < 20; i++) fprintf(stderr, " %5d", count[i]);
00318 cerr << endl << " ";
00319 for (i = 20; i < 30; i++) fprintf(stderr, " %5d", count[i]);
00320
00321 cerr << endl << " total = " << n_dt
00322 << ", weighted timestep sum = "
00323 << total_steps/n_dt << endl;
00324
00325 if (n_dt_u > 0) {
00326
00327 cerr << endl << " all nodes (actual steps):"
00328 << endl << " ";
00329 for (i = 0; i < 10; i++) fprintf(stderr, " %5d", count_a[i]);
00330 cerr << endl << " ";
00331 for (i = 10; i < 20; i++) fprintf(stderr, " %5d", count_a[i]);
00332 cerr << endl << " ";
00333 for (i = 20; i < 30; i++) fprintf(stderr, " %5d", count_a[i]);
00334
00335 cerr << endl << " total = " << n_dt
00336 << ", weighted timestep sum = "
00337 << total_steps_a/n_dt << endl;
00338
00339 if (n_dt_p > 0) {
00340 cerr << endl << " excluding unperturbed systems:"
00341 << endl << " ";
00342 for (i = 0; i < 10; i++) fprintf(stderr, " %5d", count_p[i]);
00343 cerr << endl << " ";
00344 for (i = 10; i < 20; i++) fprintf(stderr, " %5d", count_p[i]);
00345 cerr << endl << " ";
00346 for (i = 20; i < 30; i++) fprintf(stderr, " %5d", count_p[i]);
00347
00348 cerr << endl << " total = " << n_dt_p
00349 << ", weighted timestep sum = "
00350 << total_steps_p/n_dt_p
00351 << endl;
00352 }
00353
00354 cerr << endl << " unperturbed systems only:"
00355 << endl << " ";
00356 for (i = 0; i < 10; i++) fprintf(stderr, " %5d", count_u[i]);
00357 cerr << endl << " ";
00358 for (i = 10; i < 20; i++) fprintf(stderr, " %5d", count_u[i]);
00359 cerr << endl << " ";
00360 for (i = 20; i < 30; i++) fprintf(stderr, " %5d", count_u[i]);
00361
00362 cerr << endl << " total = " << n_dt_u << endl;
00363
00364 cerr << endl << " unperturbed systems only (effective blocks):"
00365 << endl << " ";
00366 for (i = 0; i < 10; i++) fprintf(stderr, " %5d", count_ue[i]);
00367 cerr << endl << " ";
00368 for (i = 10; i < 20; i++) fprintf(stderr, " %5d", count_ue[i]);
00369 cerr << endl << " ";
00370 for (i = 20; i < 30; i++) fprintf(stderr, " %5d", count_ue[i]);
00371 cerr << endl;
00372 }
00373
00374 cerr << endl
00375 << " next_step distribution (all nodes):"
00376 << endl << " ";
00377 for (i = 0; i < 10; i++) fprintf(stderr, " %5d", count_next[i]);
00378 cerr << endl << " ";
00379 for (i = 10; i < 20; i++) fprintf(stderr, " %5d", count_next[i]);
00380 cerr << endl << " ";
00381 for (i = 20; i < 30; i++) fprintf(stderr, " %5d", count_next[i]);
00382 cerr << endl;
00383
00384
00385
00386 if (n > NBOT+NTOP) {
00387
00388
00389
00390 cerr << endl << " " << NBOT << " shortest perturbed time steps:"
00391 << endl << endl;
00392
00393 qsort((void *)list_dt, (size_t)np, sizeof(dt_pair), compare_dt);
00394
00395 for (i = 0; i < NBOT; i++)
00396 fprintf(stderr, " %3d. %-15s %.4e\n",
00397 i+1,
00398 list_dt[i].b->format_label(),
00399 list_dt[i].dt);
00400
00401
00402
00403 cerr << endl << " " << NBOT << " shortest effective block steps:"
00404 << endl << endl;
00405
00406 qsort((void *)list_dtb, (size_t)n, sizeof(dt_pair), compare_dt);
00407
00408 for (i = 0; i < NBOT; i++)
00409 fprintf(stderr, " %3d. %-15s %3d %.4e %.4e\n",
00410 i+1,
00411 list_dtb[i].b->format_label(),
00412 -(int)list_dtb[i].dt,
00413 pow(2.0, list_dtb[i].dt),
00414 list_dtb[i].dt_a);
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426 qsort((void *)steps_inst, (size_t)np, sizeof(count_pair),
00427 compare_steps);
00428 qsort((void *)steps_delta, (size_t)n, sizeof(count_pair),
00429 compare_steps);
00430 qsort((void *)f_dir_delta, (size_t)nd, sizeof(count_pair),
00431 compare_steps);
00432 qsort((void *)f_ind_delta, (size_t)ni, sizeof(count_pair),
00433 compare_steps);
00434
00435 cerr << endl << " Top " << NTOP
00436 << " nodes by instantaneous (excl. unperturbed)"
00437 << " and delta (all) steps:"
00438 << endl << endl;
00439
00440 fprintf(stderr, " %-26s %-30s\n",
00441 "--- instantaneous ---",
00442 "------- delta -------");
00443 fprintf(stderr, " %-26s %-30s\n\n",
00444 "(normalized to dt = 1) ",
00445 "(since last log output)");
00446
00447 char tmp[1024];
00448
00449 for (i = 0; i < NTOP; i++) {
00450
00451 if (i < np)
00452 sprintf(tmp, "%3d. %-10s %10.0f",
00453 i+1,
00454 steps_inst[i].b->format_label(),
00455 steps_inst[i].count);
00456 else
00457 strcpy(tmp, " ");
00458 fprintf(stderr, " %-35s", tmp);
00459
00460 if (i < n)
00461 sprintf(tmp, "%-10s %10.0f",
00462 steps_delta[i].b->format_label(),
00463 steps_delta[i].count);
00464 else
00465 strcpy(tmp, " ");
00466 fprintf(stderr, " %-30s\n", tmp);
00467 }
00468 cerr << endl << " total delta_steps = " << delta_steps_tot << endl;
00469
00470 cerr << endl << " Top " << NTOP
00471 << " nodes by delta(force calculations):"
00472 << endl << endl;
00473
00474 fprintf(stderr, " %-26s %-30s\n",
00475 "------- direct ------",
00476 "------ indirect -----");
00477
00478 for (i = 0; i < NTOP; i++) {
00479
00480 if (i < nd)
00481 sprintf(tmp, "%3d. %-10s %10.0f",
00482 i+1,
00483 f_dir_delta[i].b->format_label(),
00484 f_dir_delta[i].count);
00485 else
00486 strcpy(tmp, " ");
00487 fprintf(stderr, " %-35s", tmp);
00488
00489 if (i < ni && f_ind_delta[i].count > 0)
00490 sprintf(tmp, "%-10s %10.0f",
00491 f_ind_delta[i].b->format_label(),
00492 f_ind_delta[i].count);
00493 else
00494 strcpy(tmp, " ");
00495 fprintf(stderr, " %-30s\n", tmp);
00496 }
00497 cerr << endl << " total delta_f_dir = " << delta_f_dir_tot
00498 << " delta_f_ind = " << delta_f_dir_tot
00499 << endl;
00500 }
00501
00502 delete [] list_dt;
00503 delete [] steps_inst;
00504 delete [] steps_delta;
00505 delete [] f_dir_delta;
00506 delete [] f_ind_delta;
00507 }
00508
00509 void print_dstar_params(dyn* b)
00510 {
00511 if (((hdyn*)b)->get_use_dstar())
00512 print_binary_dstars(b);
00513 }
00514
00515 bool print_dstar_stats(dyn* b, bool mass_function,
00516 vector center, bool verbose)
00517 {
00518 if (((hdyn*)b)->get_use_dstar()) {
00519 dstar_stats(b, mass_function, center, verbose);
00520
00521 return true;
00522 }
00523
00524 return false;
00525 }
00526
00527 void print_statistics(hdyn* b,
00528 int long_binary_output)
00529 {
00530
00531
00532
00533 sys_stats(b,
00534 0.5,
00535 true,
00536 (long_binary_output > 0),
00537 (long_binary_output > 1),
00538 2,
00539 false,
00540 false,
00541 false,
00542 kira_calculate_energies,
00543 print_dstar_params,
00544 print_dstar_stats);
00545
00546
00547
00548 print_timestep_stats(b);
00549 print_sort_counters();
00550 }
00551
00552 local int n_bound(hdyn* b, vector& cod_vel)
00553 {
00554 int nb = 0;
00555 for_all_daughters(hdyn, b, bb)
00556 if (0.5*square(bb->get_vel()-cod_vel) + bb->get_pot() < 0)
00557 nb += bb->n_leaves();
00558 return nb;
00559 }
00560
00561 local real m_bound(hdyn* b, vector& cod_vel)
00562 {
00563 real mb = 0;
00564 for_all_daughters(hdyn, b, bb)
00565 if (0.5*square(bb->get_vel()-cod_vel) + bb->get_pot() < 0)
00566 mb += bb->get_mass();
00567 return mb;
00568 }
00569
00570 local void get_n_and_m_bound(hdyn* b, vector& cod_vel, int& nb, real& mb)
00571 {
00572 nb = 0;
00573 mb = 0;
00574 for_all_daughters(hdyn, b, bb)
00575 if (0.5*square(bb->get_vel()-cod_vel) + bb->get_pot() < 0) {
00576 nb += bb->n_leaves();
00577 mb += bb->get_mass();
00578 }
00579 }
00580
00581
00582
00583 void update_cpu_counters(hdyn * b)
00584 {
00585 real last_cpu = b->get_kira_counters()->cpu_time;
00586 b->get_kira_counters()->cpu_time = cpu_time();
00587 b->get_kira_counters()->total_cpu_time += (cpu_time() - last_cpu);
00588 write_counters_to_log(b);
00589 }
00590
00591 void log_output(hdyn * b, real count, real steps,
00592 kira_counters* kc_prev,
00593 int long_binary_output)
00594 {
00595
00596
00597 vector cod_pos, com_vel, cod_vel;
00598 compute_com(b, cod_pos, com_vel);
00599 cod_vel = com_vel;
00600
00601
00602
00603
00604
00605
00606 real cpu = cpu_time();
00607 cerr << endl << "Computing densities..." << flush;
00608 kira_compute_densities(b, cod_pos, cod_vel);
00609
00610 cpu = cpu_time() - cpu;
00611 if (cpu < 0) cpu = 0;
00612 PRL(cpu);
00613
00614
00615
00616 int n_bound;
00617 real m_bound;
00618 get_n_and_m_bound(b, cod_vel, n_bound, m_bound);
00619
00620 cerr << endl;
00621 for (int k = 0 ; k < 40; k++) cerr << '-';
00622 cerr << endl << endl
00623 << "Time = " << b->get_system_time()
00624 << " N = " << b->n_leaves() << " (" << n_bound << " bound)"
00625 << " mass = " << total_mass(b) << " (" << m_bound << " bound)"
00626 << endl
00627 << " block steps = " << count
00628 << " total steps = " << steps
00629 << " steps per block = " << steps/max(1.0, count)
00630 << endl;
00631
00632 if (b->get_use_sstar())
00633 print_sstar_time_scales(b);
00634
00635 int p = cerr.precision(INT_PRECISION);
00636 print_recalculated_energies(b, true, true);
00637
00638
00639
00640 unsigned int ext = b->get_external_field();
00641 if (ext) {
00642 cerr << " external potential = " << get_external_pot(b)
00643 << " (";
00644 print_external(ext);
00645 cerr << ")" << endl;
00646 }
00647 cerr << " CM kinetic energy = "
00648 << 0.5*b->get_mass()*square(com_vel) << endl;
00649
00650 cerr.precision(p);
00651
00652
00653
00654
00655
00656 if (steps > 0) {
00657 update_cpu_counters(b);
00658 print_counters(b->get_kira_counters(), kc_prev);
00659 }
00660
00661 print_statistics(b, long_binary_output);
00662 cerr << flush;
00663 }
00664
00665 void snap_output(hdyn * b, real steps, int& snaps,
00666 bool reg_snap, bool last_snap,
00667 char * snap_save_file,
00668 xreal t, xreal ttmp, real t_end,
00669 real& t_snap, real dt_snap, bool verbose)
00670 {
00671
00672
00673 update_cpu_counters(b);
00674 b->set_time(t);
00675
00676 if (last_snap) {
00677
00678
00679
00680 ofstream file(snap_save_file);
00681
00682 if (file) {
00683 set_complete_system_dump(true);
00684 put_node(file, *b, b->get_kira_options()->print_xreal);
00685 set_complete_system_dump(false);
00686 file.close();
00687 cerr << "Snapshot saved in file "
00688 << snap_save_file
00689 << " (save CPU = "
00690 << cpu_time() - b->get_kira_counters()->cpu_time
00691 << ")\n";
00692 } else {
00693 if (snap_save_file == NULL)
00694 cerr << "No save file specified.\n";
00695 else
00696 cerr << "Error opening save file "
00697 << snap_save_file << "\n";
00698 }
00699 }
00700
00701 if (reg_snap) {
00702
00703 if (verbose) cerr << endl;
00704 cerr << "Snapshot output #" << ++snaps
00705 << " at steps = " << steps
00706 << ", time = " << b->get_system_time() << endl;
00707 if (verbose) cerr << endl;
00708
00709 set_complete_system_dump(true);
00710 put_node(cout, *b, b->get_kira_options()->print_xreal);
00711 set_complete_system_dump(false);
00712 cout << flush;
00713
00714
00715 }
00716 }