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