Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

red_star_cluster.C

Go to the documentation of this file.
00001 /*
00002  *  red_stelar system.C: reduce some useful information from the
00003  *                       stellar system
00004  *.............................................................................
00005  *    version 1:  Jan 1997   Simon Portegies Zwart   email: spz@astro.uva.nl
00006  *.............................................................................
00007  *  non-local function: 
00008  *  all functions are local
00009  *.............................................................................
00010  *  Input options:
00011  *     -B:      Binning option of the Lagrangian radii.
00012  *     -C:      Cut off criterion, mass, luminosity, number of stars.
00013  *     -l:      Lower luminosity limit (see below).
00014  *     -n:      Number of Lagrangian radii bins.
00015  *              Might for some choices be forced.
00016  *     -o:      Output the story with data written in root.
00017  *     -S:      Sort option, on what parameter must information be sorted.
00018  *.............................................................................
00019  *  Concerning the Lower luminosity limit option (-l, see above).
00020  *    Currently this option is only applied to the sorting functions.
00021  *    This means that the binning (using Lagrangian radii) is applied
00022  *    on all cluster members.
00023  *    whether or not this is realistic depends on the application.
00024  *    Consequently, the luminosity cut-off does not affect the
00025  *    Lagrangian radii.
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;  // sorted on this parameter.
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   // Normally all stars with L>l_min are visible.
00140   // bool visible = (star.L_eff>l_min?1:0);
00141 
00142   bool visible = false;
00143   if (star.L_eff>=l_min
00144       && (int)star_type != (int)Inert_Remnant)  // casts added by Steve!!
00145     visible = true;
00146 
00147   // However, remnants are only visible if l_min is very small.
00148   // Neutron stars are intrinsically bright but extreme blue!
00149   // only if l_min==0, all stars are visible.
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 // Determine the potential energy of bi with respect to bj, along
00188 // with bi's nearest neighbor and minimum neighbor distance.
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 // compute_energies: calculate the appropriate color code for particle bi
00208 //                   relative to "particle" bj (usually the root node).
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  *  compute_mean_cod -- Returns the position and velocity of the density
00254  *                      center of an N-body system.
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;                        // weight factor
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 //  while(prev_n_bound != n_bound);
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     //    for_all_daughters(dyn, b, d)
00309     //      if (!bound_object(b, d))
00310     //  cerr << d->get_index() <<" "
00311     //       << d->get_mass()*to_msun << " "
00312     //       << abs(d->get_pos()-center) * to_pc << " "
00313     //       << abs(d->get_vel()-vcore) *to_kms << endl;        
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;                        // weight factor
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     //PRI(4); PRL(density_center);
00346     //PRI(4); PRC(rcore); PRC(ncore); PRL(mcore);
00347 
00348     //place the data in the root dyn-story.
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   //    cerr << "rn_1 = " << bin_param[0] << endl;
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   // return if unresonable input is given.
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     // determine the lagrangian radii.
00408   for (i=0; i<nzones; i++)
00409     bin_percent[i] = lagrangian_radius(i, nzones, binning)*total_number;
00410 
00411     // write the lagrangian parameter to the *dyn story.
00412   char r_n[3];
00413   sprintf(r_n, "rn_");
00414 
00415 
00416     // read back from *dyn the lagrangian parameter.
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     //       cerr << r_n << k+1  << " = " << bin_param[k] << endl;
00432   }
00433 
00434   delete []bin_percent;
00435   
00436   //  if (scale)
00437   //     for (int k=0; k<nzones; k++) 
00438   //     bin_param[k] *= to_pc;
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   // return if unresonable input is given.
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     // determine the lagrangian parameter.
00464   for (i=0; i<nzones; i++)
00465     bin_percent[i] = lagrangian_radius(i, nzones, binning) * m_tot;
00466 
00467     // write the lagrangiant radii to the *dyn story.
00468   char r_n[3];
00469   sprintf(r_n, "rm_");
00470 
00471     // read back from *dyn the lagrangian radii.
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     //       cerr << r_n << k+1  << " = " << bin_param[k] << endl;
00489   }
00490 
00491   delete []bin_percent;
00492 
00493   //  if (scale)
00494   //     for (int k=0; k<nzones; k++) 
00495   //     bin_param[k] *= to_msun;
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   // return if unresonable input is given.
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     // determine the lagrangian parameters.
00521   for (i=0; i<nzones; i++)
00522     bin_percent[i] = lagrangian_radius(i, nzones, binning) * total_lumi;
00523 
00524     // write the lagrangiant parameter to the *dyn story.
00525   char r_n[3];
00526   sprintf(r_n, "rl_");
00527 
00528     // read back from *dyn the lagrangian radii.
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     //       cerr << r_n << k+1  << " = " << table[i-1].sort_param << endl;
00546   }
00547 
00548   delete []bin_percent;
00549 
00550   //  if (scale)
00551   //     for (int k=0; k<nzones; k++) 
00552   //     bin_param[k] *= to_pc;
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;                      // Heggie/Binney & Tremaine
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       //weight = bi->get_mass();
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     //    if (scale_flag) {
00620     //      v_cum *= to_kms;    
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 // the luminosity limit affects the cumulative luminosity, not the mass!
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 //  compare_radii  --  compare the radii of two particles
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 //  compare_parameters  --  compare parameters of two particles
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   // Use the geometric center if the density center is unknown.
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   // fill table with usefull information.
01004   // note that this part might needs a flattening of the tree.
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         // XXX co_core too?
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     table[i].type = (stellar_type_summary)1;
01038     table[i].age = table[i].dmass; 
01039     table[i].m_rel = table[i].dmass; 
01040     table[i].m_tot = table[i].dmass; 
01041     table[i].m_core = table[i].dmass; 
01042     table[i].T_eff = table[i].dmass; 
01043     table[i].L_eff = table[i].dmass; 
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     // now the array table is sorted in radius.
01054     // we can do all kind of beautiful things with it.
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   //       put_lagrangian_parameters(b, table,   nzones, n, l_min, binning);
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   //Print zero's to allow automatic ploting program to take over.
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  *  main  --  driver to use  compute_mass_radii() as a tool
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;             // minimum visible luminosity in Lsun.
01229   int nzones = 50;
01230   bool  c_flag = FALSE;      /* if TRUE: a comment given on command line   */
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     //cerr << "scalings" << to_myear << " "
01298     //                   << to_msun  << " "
01299     //                   << to_rsun  << " "
01300     //                   << to_kms   << endl;
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

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