00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "stardyn_util.h"
00030
00031 #ifdef TOOLBOX
00032
00033 #define SCRATCH_PAD_LINE_LENGTH 255
00034
00035 char* stellar_type_summ_string = "ZAMS\tEarly_G\tLate_G\tHelium\tInert\tUnknown";
00036
00037 #define MAX_PREDEF_RADII 8
00038 enum bin_option {lineair, predefined
00039 };
00040
00041 enum sort_option {distance_to_com, stellar_mass, stellar_luminosity
00042 };
00043
00044 enum cut_option {lagrangian_number_radii,
00045 lagrangian_mass_radii, lagrangian_lumi_radii,
00046 };
00047
00048 enum output_option {velocity_anisotropy, dispersion_velocity, number_of_stars,
00049 number_of_star_types, total_mass_out, mass_over_light,
00050 mean_mass, number_density, mass_density
00051 };
00052
00053 static real to_kms=1;
00054 static real to_myear=1;
00055 static real to_msun=1;
00056 static real to_rsun=1;
00057 static real to_pc=1;
00058
00059 typedef struct {
00060 real sort_param;
00061
00062 stellar_type_summary type;
00063 real age;
00064 real m_rel;
00065 real m_tot;
00066 real m_core;
00067 real T_eff;
00068 real L_eff;
00069
00070 real radius;
00071 real dmass;
00072 vector vel;
00073 vector pos;
00074 } star_table, *star_table_ptr;
00075
00076 local bool check_input_option(bin_option binning, cut_option
00077 radius_cut, sort_option sort_param, output_option option) {
00078
00079
00080 bool bin_choice = FALSE;
00081 switch(binning) {
00082 case lineair:
00083 case predefined:
00084 bin_choice = true;
00085 break;
00086 case '?': bin_choice = false;
00087 }
00088
00089 bool cut_choice = FALSE;
00090 switch(radius_cut) {
00091 case lagrangian_number_radii:
00092 cut_choice = TRUE;
00093 cerr << "Equal number of stars per bin.\n";
00094 break;
00095 case lagrangian_mass_radii:
00096 cut_choice = TRUE;
00097 cerr << "Equal mass per bin.\n";
00098 break;
00099 case lagrangian_lumi_radii:
00100 cut_choice = TRUE;
00101 cerr << "Equal luminosity per bin.\n";
00102 break;
00103 case '?': cut_choice = FALSE;
00104 }
00105
00106 bool sort_choice = false;
00107 switch(sort_param) {
00108 case distance_to_com: sort_choice = true;
00109 cerr << "Sorted on distance to cluster center.\n";
00110 break;
00111 case stellar_mass: sort_choice = true;
00112 cerr << "Sorted on stellar mass.\n";
00113 break;
00114 case stellar_luminosity: sort_choice = true;
00115 cerr << "Sorted on stellar luminosity.\n";
00116 break;
00117 case '?': sort_choice = false;
00118 }
00119
00120 bool output_choice = FALSE;
00121 switch(option) {
00122 case velocity_anisotropy:
00123 case dispersion_velocity:
00124 case number_of_stars:
00125 case number_of_star_types:
00126 case mass_over_light:
00127 case total_mass_out:
00128 case mean_mass:
00129 output_choice = TRUE;
00130 break;
00131 case '?': output_choice = FALSE;
00132 }
00133
00134 return (bin_choice && cut_choice && sort_choice);
00135 }
00136
00137 local bool visible_object(star_table star, real l_min) {
00138
00139
00140
00141
00142 bool visible = false;
00143 if (star.L_eff>=l_min
00144 && (int)star_type != (int)Inert_Remnant)
00145 visible = true;
00146
00147
00148
00149
00150 if (l_min <=0 && star.type == Inert_Remnant)
00151 visible = true;
00152
00153 return visible;
00154 }
00155
00156 local real predifinced_lagrangian_fraction(int i) {
00157
00158 real bin_radius;
00159 switch(i) {
00160 case 0: bin_radius = 0.02;
00161 break;
00162 case 1: bin_radius = 0.05;
00163 break;
00164 case 2: bin_radius = 0.10;
00165 break;
00166 case 3: bin_radius = 0.20;
00167 break;
00168 case 4: bin_radius = 0.30;
00169 break;
00170 case 5: bin_radius = 0.50;
00171 break;
00172 case 6: bin_radius = 0.70;
00173 break;
00174 case 7: bin_radius = 0.90;
00175 break;
00176 default: bin_radius = 1;
00177 }
00178
00179 return bin_radius;
00180 }
00181
00182
00183
00184 local void accumulate_potential_energy(dyn* bj, dyn*bi,
00185 real& epot, real& rmin, dynptr& bmin)
00186
00187
00188
00189
00190 {
00191 if (bj->get_oldest_daughter() != (dyn*)NULL)
00192 for (dyn * bb = bj->get_oldest_daughter(); bb != (dyn*)NULL;
00193 bb = bb->get_younger_sister()) {
00194 accumulate_potential_energy(bb, bi, epot, rmin, bmin);
00195 }
00196 else
00197 if (bi != bj) {
00198 vector d_pos = bi->get_pos() - bj->get_pos();
00199 real mi = bi->get_mass();
00200 real mj = bj->get_mass();
00201 real r = sqrt(d_pos * d_pos);
00202 epot += -mi*mj/r;
00203 if (r < rmin) {rmin = r; bmin = bj;}
00204 }
00205 }
00206
00207
00208
00209
00210 local bool bound_object(dyn* bj, dyn* bi)
00211 {
00212 bool bound = true;
00213
00214 real epot = 0, rmin = VERY_LARGE_NUMBER;
00215 dynptr bmin = bi;
00216
00217 accumulate_potential_energy(bj, bi, epot, rmin, bmin);
00218
00219 real mi = bi->get_mass();
00220 real mj = bmin->get_mass();
00221 vector d_vel = bi->get_vel() - bmin->get_vel();
00222 vector d_pos = bi->get_pos() - bmin->get_pos();
00223 real r = sqrt(d_pos * d_pos);
00224 real e0 = (0.5 * d_vel * d_vel - (mi + mj)/r);
00225
00226 if (e0 < 0) {
00227 real epot1 = 0, rmin1 = VERY_LARGE_NUMBER;
00228 dynptr bmin1 = bi;
00229
00230 accumulate_potential_energy(bj, bmin, epot1, rmin1, bmin1);
00231
00232 if (bi == bmin1) {
00233 real e = - mi*mj / r;
00234 vector R_vel = (mi*bi->get_vel()+mj*bmin->get_vel())/(mi+mj);
00235 real ekin = 0.5*(mi+mj)*R_vel*R_vel;
00236
00237 if (epot + epot1 - 2*e + ekin < 0) bound = true;
00238 else bound = false;
00239
00240 } else bound = true;
00241
00242 } else {
00243 vector vel = bi->get_vel();
00244 real ekin = 0.5*bi->get_mass()*vel*vel;
00245
00246 if (ekin + epot > 0.0) bound = false;
00247 }
00248
00249 return bound;
00250 }
00251
00252
00253
00254
00255
00256
00257 void compute_cod_velocity(dyn *b, vector& vel)
00258 {
00259 real total_weight = 0;
00260 int prev_n_bound, n_bound = 0;
00261
00262 vector old_vel;
00263 real dvel = 0;
00264 do {
00265
00266 old_vel = vel;
00267 vel = 0;
00268
00269 prev_n_bound = n_bound;
00270 n_bound = 0;
00271
00272 for_all_daughters(dyn, b, d) {
00273
00274 real density = getrq(d->get_dyn_story(), "density");
00275 real dens2 = density * density;
00276
00277 if (bound_object(b, d)) {
00278 n_bound++;
00279 total_weight += dens2;
00280 vel += dens2 * d->get_vel();
00281 }
00282 }
00283 vel /= total_weight;
00284
00285 dvel = abs(old_vel - vel);
00286
00287 b->set_vel(vel);
00288 cerr << " number of bound objects: " << n_bound <<endl;
00289 cerr << " density center velocity: " << vel << endl;
00290 }
00291 while(dvel>0.01);
00292
00293
00294
00295 }
00296
00297 local
00298 void compute_core_parameters(dyn* b, int k, vector& center, vector &vcore,
00299 real& rcore, int& ncore, real& mcore)
00300 {
00301 compute_density(b, k);
00302 compute_mean_cod(b, center, vcore);
00303
00304 b->set_vel(vcore);
00305 compute_cod_velocity(b, vcore);
00306 cerr << " density center position: " << center << endl;
00307
00308
00309
00310
00311
00312
00313
00314
00315 real total_weight = 0;
00316 real sum = 0;
00317 for_all_daughters(dyn, b, bi) {
00318 real density = getrq(bi->get_dyn_story(), "density");
00319 real dens2 = density * density;
00320
00321 total_weight += dens2;
00322 sum += dens2 * square(bi->get_pos() - center);
00323 }
00324
00325 real rcore2 = sum/total_weight;
00326 rcore = sqrt(rcore2);
00327 ncore = 0;
00328 mcore = 0;
00329
00330 for_all_daughters(dyn, b, bj)
00331 if (square(bj->get_pos() - center) <= rcore2) {
00332 ncore++;
00333 mcore += bj->get_mass();
00334 }
00335 }
00336
00337 local void print_core_parameters(dyn* b, vector& density_center,
00338 vector &vcore,
00339 real& rcore) {
00340
00341 real mcore;
00342 int ncore;
00343
00344 compute_core_parameters(b, 6, density_center, vcore, rcore, ncore, mcore);
00345
00346
00347
00348
00349 putvq(b->get_dyn_story(), "density_center_pos", density_center);
00350 putrq(b->get_dyn_story(), "core_radius", rcore);
00351 putiq(b->get_dyn_story(), "n_core", ncore);
00352 putrq(b->get_dyn_story(), "m_core", mcore);
00353 }
00354
00355 local real lagrangian_radius(int i, int nzones,
00356 bin_option binning) {
00357
00358 real bin;
00359 if (binning == predefined && nzones==MAX_PREDEF_RADII)
00360 bin = predifinced_lagrangian_fraction(i);
00361 else
00362 bin = ((i + 1) / (real)nzones);
00363
00364 return bin;
00365 }
00366
00367 local real* the_whole_cluster(dyn* b, star_table_ptr table, int n,
00368 real l_min) {
00369
00370 if (n==0)
00371 n = b->n_daughters();
00372 real *bin_param = new real[1];
00373
00374 cerr << "\t" << max(0.0, b->get_system_time()) << "\t" << 1 << endl;
00375
00376 int i=n-1;
00377 while(!visible_object(table[i--], l_min));
00378
00379 bin_param[0] = table[i].sort_param;
00380
00381
00382
00383 return bin_param;
00384 }
00385
00386 local real* put_lagrangian_number_radii(dyn* b, star_table_ptr table,
00387 int nzones, int n, real l_min,
00388 bin_option binning) {
00389
00390
00391 if (nzones < 2)
00392 return the_whole_cluster(b, table, n, l_min);
00393
00394
00395 if (n==0)
00396 n = b->n_daughters();
00397
00398 real* bin_percent = new real[nzones];
00399 real* bin_param = new real[nzones];
00400
00401 int i;
00402 real total_number=0;
00403 for (i=0; i<n; i++)
00404 if (visible_object(table[i], l_min))
00405 total_number += 1;
00406
00407
00408 for (i=0; i<nzones; i++)
00409 bin_percent[i] = lagrangian_radius(i, nzones, binning)*total_number;
00410
00411
00412 char r_n[3];
00413 sprintf(r_n, "rn_");
00414
00415
00416
00417 char scratch_pad[SCRATCH_PAD_LINE_LENGTH];
00418 sprintf(scratch_pad, "n_number_zones = %d", nzones);
00419 cerr << "\t" << max(0.0, b->get_system_time()) << "\t" << nzones << endl;
00420
00421 real cumulative = 0;
00422 i = 0;
00423 for (int k=0; k<nzones; k++) {
00424 while (cumulative < bin_percent[k])
00425 if (visible_object(table[i++], l_min))
00426 cumulative += 1;
00427
00428 bin_param[k] = table[i-1].sort_param;
00429 sprintf(scratch_pad, "%s%d = %f", r_n, k+1, table[i-1].sort_param);
00430 add_story_line(b->get_log_story(), scratch_pad);
00431
00432 }
00433
00434 delete []bin_percent;
00435
00436
00437
00438
00439
00440 return bin_param;
00441 }
00442
00443 local real* put_lagrangian_mass_radii(dyn* b, star_table_ptr table,
00444 int nzones, int n, real l_min,
00445 bin_option binning) {
00446
00447
00448 if (nzones < 2)
00449 return the_whole_cluster(b, table, n, l_min);
00450
00451 if (n==0)
00452 n = b->n_daughters();
00453
00454 real* bin_percent = new real[nzones];
00455 real* bin_param = new real[nzones];
00456
00457 int i;
00458 real m_tot=0;
00459 for (i=0; i<n; i++)
00460 if (visible_object(table[i], l_min))
00461 m_tot += table[i].sort_param;
00462
00463
00464 for (i=0; i<nzones; i++)
00465 bin_percent[i] = lagrangian_radius(i, nzones, binning) * m_tot;
00466
00467
00468 char r_n[3];
00469 sprintf(r_n, "rm_");
00470
00471
00472 char scratch_pad[SCRATCH_PAD_LINE_LENGTH];
00473 sprintf(scratch_pad, "n_mass_zones = %d", nzones);
00474 cerr << "\t" << max(0.0, b->get_system_time()) << "\t" << nzones << endl;
00475
00476 real cumulative = 0;
00477 i = 0;
00478 for (int k=0; k<nzones; k++) {
00479 while (cumulative < bin_percent[k]) {
00480 if (visible_object(table[i], l_min))
00481 cumulative += table[i].sort_param;
00482 i++;
00483 };
00484
00485 bin_param[k] = table[i-1].sort_param;
00486 sprintf(scratch_pad, "%s%d = %f", r_n, k+1, table[i-1].sort_param);
00487 add_story_line(b->get_log_story(), scratch_pad);
00488
00489 }
00490
00491 delete []bin_percent;
00492
00493
00494
00495
00496
00497 return bin_param;
00498 }
00499
00500 local real* put_lagrangian_lumi_radii(dyn* b, star_table_ptr table,
00501 int nzones, int n, real l_min,
00502 bin_option binning) {
00503
00504
00505 if (nzones < 2)
00506 return the_whole_cluster(b, table, n, l_min);
00507
00508 if (n==0)
00509 n = b->n_daughters();
00510
00511 real* bin_percent = new real[nzones];
00512 real* bin_param = new real[nzones];
00513
00514 int i;
00515 real total_lumi=0;
00516 for (i=0; i<n; i++)
00517 if (visible_object(table[i], l_min))
00518 total_lumi += table[i].sort_param;
00519
00520
00521 for (i=0; i<nzones; i++)
00522 bin_percent[i] = lagrangian_radius(i, nzones, binning) * total_lumi;
00523
00524
00525 char r_n[3];
00526 sprintf(r_n, "rl_");
00527
00528
00529 char scratch_pad[SCRATCH_PAD_LINE_LENGTH];
00530 sprintf(scratch_pad, "n_lumi_zones = %d", nzones);
00531 cerr << "\t" << max(0.0, b->get_system_time()) << "\t" << nzones << endl;
00532
00533 real cumulative = 0.0;
00534 i = 0;
00535 for (int k=0; k<nzones; k++) {
00536 while (cumulative < bin_percent[k]) {
00537 if (visible_object(table[i], l_min))
00538 cumulative += table[i].L_eff;
00539 i++;
00540 };
00541
00542 bin_param[k] = table[i-1].sort_param;
00543 sprintf(scratch_pad, "%s%d = %f", r_n, k+1, table[i-1].sort_param);
00544 add_story_line(b->get_log_story(), scratch_pad);
00545
00546 }
00547
00548 delete []bin_percent;
00549
00550
00551
00552
00553
00554 return bin_param;
00555 }
00556
00557 local void extr_velocity_anisotopy(star_table_ptr table,
00558 int n, real zone, int nstar, real l_min,
00559 bool verbatim) {
00560 real v2, vr, vr2;
00561 real total_weight =0;
00562 real vr2_sum = 0;
00563 real vt2_sum = 0;
00564
00565 real weight = 1;
00566 int i = nstar;
00567 int n_stars = 0;
00568 while (table[i++].sort_param < zone)
00569 if (visible_object(table[i], l_min)) {
00570 n_stars++;
00571
00572
00573
00574 v2 = table[i].vel * table[i].vel;
00575 vr = table[i].pos * table[i].vel;
00576 vr2 = vr * vr / square(table[i].pos);
00577
00578 total_weight += weight;
00579 vr2_sum += weight * vr2;
00580 vt2_sum += weight * (v2 - vr2);
00581 }
00582
00583 if (i>nstar)
00584 cerr << 1 - 0.5 * vt2_sum / vr2_sum << " ";
00585 else
00586 cerr << 0 << " ";
00587 }
00588
00589 local void extr_dispersion_velocity(star_table_ptr table, int n,
00590 real* zones, int nzones, real l_min,
00591 bool scale_flag,
00592 bool verbatim = true) {
00593
00594 int n_stars;
00595 real v2_cum, v_cum;
00596 char scratch_pad[SCRATCH_PAD_LINE_LENGTH];
00597
00598 if (!scale_flag)
00599 cerr << "Zone \t\tdispersion velocity <v^2>^{1/2}:"<<endl;
00600 else
00601 cerr << "Zone \t\tdispersion velocity <v^2>^{1/2} [km/s]:"<<endl;
00602
00603 int i = 0;
00604 for (int k=0; k<nzones; k++) {
00605
00606 n_stars = 0;
00607 v2_cum = 0;
00608 while (table[i++].sort_param < zones[k])
00609 if (visible_object(table[i], l_min)) {
00610 v2_cum += pow(abs(table[i].vel), 2);
00611 n_stars++;
00612 }
00613
00614 v_cum=0;
00615 if (n_stars>=1) {
00616 v_cum = sqrt(v2_cum/dynamic_cast(int, n_stars));
00617 }
00618
00619
00620
00621
00622
00623 sprintf(scratch_pad, "v_disp = %lf", v_cum);
00624 if (scale_flag)
00625 cerr << k+1 << " " << zones[k]*to_pc
00626 << " \t" << v_cum*to_kms << endl;
00627 else
00628 cerr << k+1 << " " << zones[k]
00629 << " " << v_cum << endl;
00630
00631 }
00632 }
00633 local void extr_dispersion_velocity(star_table_ptr table, int n,
00634 real zone, int nstar, real l_min,
00635 bool scale_flag,
00636 bool verbatim = true) {
00637
00638 int n_stars;
00639 real v2_cum, v_cum;
00640 char scratch_pad[SCRATCH_PAD_LINE_LENGTH];
00641
00642 int i = nstar;
00643
00644 n_stars = 0;
00645 v2_cum = 0;
00646 while (table[i++].sort_param < zone)
00647 if (visible_object(table[i], l_min)) {
00648 v2_cum += pow(abs(table[i].vel), 2);
00649 n_stars++;
00650 }
00651
00652 v_cum=0;
00653 if (n_stars>=1) {
00654 v_cum = sqrt(v2_cum/dynamic_cast(int, n_stars));
00655 }
00656
00657 if (scale_flag)
00658 cerr << v_cum*to_kms << " ";
00659 else
00660 cerr << v_cum << " ";
00661
00662 }
00663
00664 local void count_stars(star_table_ptr table, int n,
00665 real zone, int nstar, real l_min,
00666 bool scale_flag = true,
00667 bool verbatim = true) {
00668
00669 int i = nstar;
00670 int n_stars = 0;
00671 while (table[i++].sort_param < zone)
00672 if (visible_object(table[i], l_min))
00673 n_stars++;
00674
00675 if (scale_flag)
00676 cerr << n_stars << " ";
00677 else
00678 cerr << n_stars << " ";
00679
00680 }
00681
00682 local void count_stars(star_table_ptr table, int n,
00683 real* zones, int nzones, real l_min,
00684 bool scale_flag = true,
00685 bool verbatim = true) {
00686
00687 int n_stars;
00688 char scratch_pad[SCRATCH_PAD_LINE_LENGTH];
00689
00690 cerr << "Zone \t\tnumber of stars:"<<endl;
00691
00692
00693 int i = 0;
00694 for (int k=0; k<nzones; k++) {
00695
00696 n_stars = 0;
00697 while (table[i++].sort_param < zones[k])
00698 if (visible_object(table[i], l_min))
00699 n_stars++;
00700
00701
00702 sprintf(scratch_pad, "n_stars = %d", n_stars);
00703 if (scale_flag)
00704 cerr << k+1 << " " << zones[k]*to_pc
00705 << " \t" << n_stars << endl;
00706 else
00707 cerr << k+1 << " " << zones[k]
00708 << " " << n_stars << endl;
00709
00710 }
00711 }
00712
00713 local void count_stellar_types(star_table_ptr table, int n,
00714 real* zones, int nzones,
00715 real l_min,
00716 bool scale_flag = true,
00717 bool verbatim = true) {
00718
00719 int* types = new int[no_of_star_type_summ];
00720
00721 int i = 0;
00722 cerr << "Zone \t\t" << stellar_type_summ_string << endl;
00723 for (int k=0; k<nzones; k++) {
00724 while (table[i++].sort_param < zones[k])
00725 if (visible_object(table[i], l_min))
00726 types[(int)table[i].type]++;
00727
00728 if (scale_flag)
00729 cerr << k+1 << " " << zones[k]*to_pc
00730 << " \t";
00731 else
00732 cerr << k+1 << " " << zones[k]
00733 << " \t";
00734
00735 for (int j=0; j<no_of_star_type_summ-1; j++) {
00736 cerr << types[j] << "\t";
00737 types[j] = 0;
00738 }
00739 cerr << endl;
00740 }
00741
00742 delete []types;
00743 }
00744
00745
00746 local int mass_over_light_ratio(star_table_ptr table, int n,
00747 real zone, int nstar, real l_min,
00748 bool verbatim = true) {
00749
00750 real ml_ratio;
00751 real mass, light;
00752
00753 int i = nstar;
00754 real m_cum, l_cum;
00755
00756 m_cum = l_cum = 0;
00757 while (table[i++].sort_param < zone) {
00758 mass = table[i].m_tot;
00759 light = table[i].L_eff;
00760 if (visible_object(table[i], l_min))
00761 l_cum += light;
00762 m_cum += mass;
00763 };
00764
00765 if (l_cum>0)
00766 ml_ratio = m_cum/l_cum;
00767 else
00768 ml_ratio = -1;
00769
00770 cerr << ml_ratio << endl;
00771
00772 return i - nstar;
00773 }
00774
00775 local void total_stellar_mass(star_table_ptr table, int n, real* zones,
00776 int nzones, real l_min,
00777 bool scale_flag = true,
00778 bool verbatim = true) {
00779
00780 real m_tot;
00781 char scratch_pad[SCRATCH_PAD_LINE_LENGTH];
00782
00783 cerr << "Zone \ttotal mass:"<<endl;
00784
00785 int i = 0;
00786 for (int k=0; k<nzones; k++) {
00787
00788 m_tot = 0;
00789 while (table[i++].sort_param < zones[k])
00790 if (visible_object(table[i], l_min))
00791 m_tot += table[i].m_tot;
00792
00793 sprintf(scratch_pad, "m_tot = %f", m_tot);
00794 if (scale_flag)
00795 cerr << k+1 << " " << zones[k]*to_pc
00796 << " \t" << m_tot << endl;
00797 else
00798 cerr << k+1 << " " << zones[k]
00799 << " \t" << m_tot/to_msun << endl;
00800 }
00801 }
00802 local void mean_stellar_mass(star_table_ptr table, int n, real zone,
00803 int nstar, real l_min,
00804 bool scale_flag, bool verbatim = true) {
00805
00806 real m_tot, n_star, mmass;
00807
00808 int i = nstar;
00809 m_tot = n_star = 0;
00810 while (table[i++].sort_param < zone)
00811 if (visible_object(table[i], l_min)) {
00812 m_tot += table[i].m_tot;
00813 n_star += 1;
00814 }
00815
00816 mmass = m_tot / n_star;
00817 if (!scale_flag)
00818 mmass /= to_msun;
00819
00820 if (scale_flag)
00821 cerr << mmass << " ";
00822 else
00823 cerr << mmass/to_msun << " ";
00824 }
00825
00826 local void mean_stellar_mass(star_table_ptr table, int n, real* zones,
00827 int nzones, real l_min,
00828 bool scale_flag, bool verbatim = true) {
00829
00830 real m_tot, n_star, mmass;
00831 char scratch_pad[SCRATCH_PAD_LINE_LENGTH];
00832
00833 if (scale_flag)
00834 cerr << "Zone \tmean mass: "<<endl;
00835 else
00836 cerr << "Zone \tmean mass [msun]:"<<endl;
00837
00838
00839 int i = 0;
00840 for (int k=0; k<nzones; k++) {
00841
00842 m_tot = n_star = 0;
00843 while (table[i++].sort_param < zones[k])
00844 if (visible_object(table[i], l_min)) {
00845 m_tot += table[i].m_tot;
00846 n_star += 1;
00847 }
00848
00849 mmass = m_tot / n_star;
00850 if (!scale_flag)
00851 mmass /= to_msun;
00852
00853 sprintf(scratch_pad, "m_tot = %f", mmass);
00854 if (scale_flag)
00855 cerr << k+1 << " " << zones[k]*to_pc
00856 << " \t" << mmass << endl;
00857 else
00858 cerr << k+1 << " " << zones[k]
00859 << " \t" << mmass/to_msun << endl;
00860 }
00861 }
00862
00863 local void stellar_number_density(star_table_ptr table, int n,
00864 real zone1, real zone2,
00865 int nstar, real l_min,
00866 bool scale_flag, bool verbatim = true) {
00867
00868 real m_tot, n_star;
00869 real area, density;
00870 real to_area = 4*cnsts.mathematics(pi);
00871
00872 real to_kubic_parsec = 1./pow(to_rsun/4.4e+7, 3);
00873
00874 int i = nstar;
00875 m_tot = n_star = 0;
00876 while (table[i++].sort_param < zone2)
00877 if (visible_object(table[i], l_min)) {
00878 m_tot += table[i].m_tot;
00879 n_star += 1;
00880 }
00881
00882 if (zone1>0)
00883 area = to_area * pow(zone1, 2) * (zone2 - zone1);
00884 else
00885 area = cnsts.mathematics(one_third) * to_area * pow(zone2, 3);
00886
00887 density = n_star/area;
00888
00889 if (scale_flag)
00890 cerr << density*to_kubic_parsec << " ";
00891 else
00892 cerr << density << " ";
00893 }
00894
00895 local void stellar_mass_density(star_table_ptr table, int n,
00896 real zone1, real zone2,
00897 int nstar, real l_min,
00898 bool scale_flag, bool verbatim = true) {
00899
00900 real m_tot, n_star;
00901 real area, density;
00902 real to_area = 4*cnsts.mathematics(pi);
00903
00904 real to_kubic_parsec = 1./pow(to_rsun/4.4e+7, 3);
00905
00906 int i = nstar;
00907
00908 m_tot = n_star = 0;
00909 while (table[i++].sort_param < zone2)
00910 if (visible_object(table[i], l_min)) {
00911 m_tot += table[i].m_tot;
00912 n_star += 1;
00913 }
00914
00915 if (zone1>0)
00916 area = to_area * pow(zone1, 2) * (zone2 - zone1);
00917 else
00918 area = cnsts.mathematics(one_third) * to_area * pow(zone2, 3);
00919
00920 density = m_tot/area;
00921
00922 if(scale_flag)
00923 cerr << density*to_kubic_parsec << " ";
00924 else
00925 cerr << density << " ";
00926 }
00927
00928
00929
00930
00931
00932
00933 local int compare_radii(const void * pi, const void * pj)
00934 {
00935 if (((star_table_ptr) pi)->radius > ((star_table_ptr) pj)->radius)
00936 return(1);
00937 else if (((star_table_ptr)pi)->radius < ((star_table_ptr)pj)->radius)
00938 return(-1);
00939 else
00940 return(0);
00941 }
00942
00943
00944
00945
00946
00947 local int compare_parameters(const void * pi, const void * pj)
00948 {
00949 if (((star_table_ptr) pi)->sort_param > ((star_table_ptr) pj)->sort_param)
00950 return(1);
00951 else if (((star_table_ptr)pi)->sort_param < ((star_table_ptr)pj)->sort_param)
00952 return(-1);
00953 else
00954 return(0);
00955 }
00956
00957 local real sorted_parameter(star_table table, sort_option sort_param) {
00958
00959 real parameter;
00960 if (sort_param==distance_to_com) {
00961 parameter = table.radius;
00962 }
00963 if (sort_param==stellar_mass) {
00964 parameter = table.dmass;
00965 }
00966 else
00967 parameter = table.L_eff;
00968
00969 return parameter;
00970 }
00971
00972
00973
00974
00975 local star_table_ptr sort_stellar_parameter(dyn * b, int nzones, int &n,
00976 sort_option sort_param) {
00977
00978 stellar_type type=NAS;
00979 story* st=NULL;
00980 real t_cur, t_rel, m_rel, m_env, m_core, co_core, t_eff, l_eff, p_rot, b_fld;
00981
00982 if (n==0)
00983 n = b->n_daughters();
00984
00985 star_table_ptr table = new star_table[n];
00986 if (table == NULL) {
00987 cerr << "sort_stellar_parameter: "
00988 << "not enough memory left for table\n";
00989 exit(0);
00990 }
00991
00992
00993 vector dc_pos = 0;
00994 vector dc_vel = 0;
00995 real rcore = 0;
00996 if (find_qmatch(b->get_dyn_story(), "density_center_pos"))
00997 dc_pos = getvq(b->get_dyn_story(), "density_center_pos");
00998 else
00999 print_core_parameters(b, dc_pos, dc_vel, rcore);
01000
01001 int i;
01002
01003
01004
01005 dyn* bi;
01006 n=0;
01007 for (i = 0, bi = b->get_oldest_daughter(); bi != NULL;
01008 bi = bi->get_younger_sister()) {
01009
01010 if (bound_object(b, bi)) {
01011
01012 table[i].radius = abs(bi->get_pos() - dc_pos);
01013 table[i].dmass = bi->get_mass();
01014
01015 st = bi->get_starbase()->get_star_story();
01016 extract_story_chapter(type, t_cur, t_rel,
01017 m_rel, m_env, m_core,
01018 co_core,
01019 t_eff, l_eff,
01020 p_rot, b_fld,
01021 *st);
01022
01023 if (summarize_stellar_type(type)==Inert_Remnant)
01024 l_eff = 0;
01025 table[i].type = summarize_stellar_type(type);
01026 table[i].age = t_rel;
01027 table[i].m_rel = m_rel;
01028 table[i].m_tot = m_env+m_core;
01029 table[i].m_core = m_core;
01030
01031 table[i].T_eff = t_eff;
01032 table[i].L_eff = l_eff;
01033 table[i].vel = bi->get_vel() -dc_vel;
01034 table[i].pos = bi->get_pos() - dc_pos;
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046 table[i].sort_param = sorted_parameter(table[i], sort_param);
01047 i++;
01048 }
01049 }
01050 n=i;
01051 qsort((void *)table, (size_t)n, sizeof(star_table), compare_parameters);
01052
01053
01054
01055
01056 return table;
01057 }
01058
01059 local void red_stellar_system(dyn* b, int nzones,
01060 bin_option binning, cut_option
01061 radius_cut, output_option option,
01062 sort_option sort_param, real l_min,
01063 bool scale_flag = false,
01064 bool verbatim = true) {
01065
01066 int n = b->n_daughters();
01067
01068 star_table_ptr table = sort_stellar_parameter(b, nzones, n, sort_param);
01069
01070 real* zones;
01071 if (nzones < 2) {
01072 zones = the_whole_cluster(b, table, n, l_min);
01073 nzones = 1;
01074 }
01075 else
01076 switch(radius_cut) {
01077 case lagrangian_number_radii:
01078 zones = put_lagrangian_number_radii(b, table,
01079 nzones, n, l_min,
01080 binning);
01081 break;
01082 case lagrangian_mass_radii:
01083 zones = put_lagrangian_mass_radii(b, table, nzones,
01084 n, l_min,
01085 binning);
01086 break;
01087 case lagrangian_lumi_radii:
01088 zones = put_lagrangian_lumi_radii(b, table, nzones,
01089 n, l_min, binning);
01090 break;
01091 case '?': cerr << "no option specified in red_stellar_system.";
01092 cerr << "use whole cluster instead.";
01093 default: zones = the_whole_cluster(b, table, n, l_min);
01094 nzones = 1;
01095 };
01096
01097
01098
01099 cerr << "i R N <m> n rho <v> vt/vr M/L" << endl;
01100 cerr << " [pc] [Msun] [*/pc^3] [km/s] [Msun/Lsun]"
01101 << endl;
01102
01103 int ncount, nstar = 0;
01104 for (int k=0; k<nzones; k++) {
01105 if (scale_flag)
01106 cerr << k+1 << " " << zones[k]*to_pc << " ";
01107 else
01108 cerr << k+1 << " " << zones[k] << " ";
01109
01110 count_stars(table, n, zones[k], nstar,
01111 l_min, scale_flag, verbatim);
01112 mean_stellar_mass(table, n, zones[k], nstar,
01113 l_min, scale_flag, verbatim);
01114 if (k==0) {
01115 stellar_number_density(table, n, 0, zones[k], nstar,
01116 l_min, scale_flag, verbatim);
01117 stellar_mass_density(table, n, 0, zones[k], nstar,
01118 l_min, scale_flag, verbatim);
01119 }
01120 else {
01121 stellar_number_density(table, n, zones[k-1], zones[k], nstar,
01122 l_min, scale_flag, verbatim);
01123 stellar_mass_density(table, n, zones[k-1], zones[k], nstar,
01124 l_min, scale_flag, verbatim);
01125 }
01126 extr_dispersion_velocity(table, n, zones[k], nstar,
01127 l_min, scale_flag, verbatim);
01128 extr_velocity_anisotopy(table, n, zones[k], nstar,
01129 l_min, verbatim);
01130 ncount = mass_over_light_ratio(table, n, zones[k], nstar,
01131 l_min, verbatim);
01132 nstar += ncount;
01133 }
01134
01135
01136 cerr << "0 0 0 0 0 0 0 0 0" <<endl;
01137
01138 #if 0
01139 switch(option) {
01140 case velocity_anisotropy:
01141 extr_velocity_anisotopy(table, n, zones, nzones,
01142 l_min, verbatim);
01143 break;
01144 case dispersion_velocity:
01145 extr_dispersion_velocity(table, n, zones, nzones,
01146 l_min, scale_flag, verbatim);
01147 break;
01148 case number_of_stars:
01149 count_stars(table, n, zones, nzones, l_min, scale_flag, verbatim);
01150 break;
01151 case number_of_star_types:
01152 count_stellar_types(table, n, zones, nzones, l_min, scale_flag, verbatim);
01153 break;
01154 case mass_over_light:
01155 mass_over_light_ratio(table, n, zones, nzones,
01156 l_min, scale_flag, verbatim);
01157 break;
01158 case total_mass_out:
01159 total_stellar_mass(table, n, zones, nzones, l_min, scale_flag, verbatim);
01160 break;
01161 case mean_mass:
01162 mean_stellar_mass(table, n, zones, nzones, l_min, scale_flag, verbatim);
01163 break;
01164 case number_density:
01165 stellar_number_density(table, n, zones, nzones, l_min, scale_flag, verbatim);
01166 break;
01167 case mass_density:
01168 stellar_mass_density(table, n, zones, nzones, l_min, scale_flag, verbatim);
01169 break;
01170 default: cerr << "no option specified in red_stellar_system.";
01171 break;
01172 };
01173 #endif
01174
01175 delete []table;
01176 delete []zones;
01177
01178 }
01179
01180 local void project(dyn *b, int axis) {
01181
01182 vector new_pos, new_vel;
01183 for_all_leaves(dyn, b, bi) {
01184 new_pos = bi->get_pos();
01185 new_vel = bi->get_vel();
01186 new_pos[axis] = 0;
01187 new_vel[axis] = 0;
01188 bi->set_pos(new_pos);
01189 bi->set_vel(new_vel);
01190 }
01191 }
01192
01193 local void print_parameter_usage() {
01194
01195 cerr << "Parameters usage for: red_stellar_system." << endl;
01196 cerr << "options:\n"
01197 << " -B: Binning option of the Lagrangian radii.\n"
01198 << " 0= lineair, 1= predefined.\n"
01199 << " -C: Cut off creterium, mass, luminosity, number of stars.\n"
01200 << " 0= by number, 1= by mass, 2= by luminosity.\n"
01201 << " -l: Lower luminosity limit.\n"
01202 << " -N: Number of Lagrangian radii bins.\n"
01203 << " Might for some choices be forced.\n"
01204 << " -n: Allow for n-squared operations.\n"
01205 << " -o: Output the story with data written in root.\n"
01206 << " -S: Sort option, on which parameter should be sorted.\n"
01207 << " 0= distance to com, 1= stellar mass.\n"
01208 << " -s: Scale to astrophysical units.\n"
01209 << " -v: give extended output\n"
01210 << endl;
01211 }
01212
01213
01214
01215
01216
01217 main(int argc, char ** argv)
01218 {
01219 char *comment;
01220 bool out = false;
01221 bool verbatim = false;
01222 bool nsq_opt = false;
01223 bool scale_flag = false;
01224 bin_option binning = lineair;
01225 cut_option radius_cut = lagrangian_mass_radii;
01226 output_option option = velocity_anisotropy;
01227 sort_option sort_param = distance_to_com;
01228 real l_min = 0.0;
01229 int nzones = 50;
01230 bool c_flag = FALSE;
01231 int axis = -1;
01232
01233 extern char *poptarg;
01234 int c;
01235 char* param_string = "a:B:C:c:l:N:noS:sv";
01236
01237 while ((c = pgetopt(argc, argv, param_string)) != -1)
01238 switch(c)
01239 {
01240 case 'a': axis = atoi(poptarg);
01241 break;
01242 case 'B': binning = (bin_option)atoi(poptarg);
01243 break;
01244 case 'C': radius_cut = (cut_option)atoi(poptarg);
01245 break;
01246 case 'c': c_flag = TRUE;
01247 comment = poptarg;
01248 break;
01249 case 'l': l_min = atof(poptarg);
01250 break;
01251 case 'N': nzones = atoi(poptarg);
01252 break;
01253 case 'n': nsq_opt = true;
01254 break;
01255 case 'o': out = true;
01256 break;
01257 case 'S': sort_param = (sort_option)atoi(poptarg);
01258 break;
01259 case 's': scale_flag = true;
01260 break;
01261 case 'v': verbatim = true;
01262 break;
01263 case '?': params_to_usage(cerr, argv[0], param_string);
01264 print_parameter_usage();
01265 exit(1);
01266 }
01267
01268 dyn *b;
01269
01270 if (!check_input_option(binning, radius_cut, sort_param, option)) {
01271 cerr << "input option not recognized!" << endl;
01272 print_parameter_usage();
01273 exit(1);
01274 }
01275 if (binning==predefined)
01276 nzones = MAX_PREDEF_RADII;
01277
01278 cerr.precision(LOW_PRECISION);
01279 vector density_center=0;
01280 vector density_velocity=0;
01281 real rcore;
01282 while (b = get_dyn(cin)) {
01283
01284 if (c_flag == TRUE)
01285 b->log_comment(comment);
01286
01287 b->log_history(argc, argv);
01288
01289 to_myear= 1./b->get_starbase()->conv_t_star_to_dyn(1);
01290 to_msun = 1./b->get_starbase()->conv_m_star_to_dyn(1);
01291 to_rsun = 1./b->get_starbase()->conv_r_star_to_dyn(1);
01292 to_pc = to_rsun * cnsts.parameters(Rsun)/cnsts.parameters(parsec);
01293 to_kms = (to_rsun* cnsts.parameters(Rsun)
01294 / cnsts.physics(kilometer))
01295 / (to_myear*cnsts.physics(Myear));
01296
01297
01298
01299
01300
01301
01302 cerr << "Time = " << b->get_system_time() << endl;
01303
01304 if (nsq_opt)
01305 print_core_parameters(b, density_center, density_velocity, rcore);
01306
01307 if(axis>=0)
01308 project(b, 0);
01309
01310 red_stellar_system(b, nzones, binning, radius_cut, option,
01311 sort_param, l_min, scale_flag, verbatim);
01312
01313 if (out) put_dyn(cout, *b);
01314 delete b;
01315 }
01316 }
01317
01318 #endif