Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

red_stellar_system.C

Go to the documentation of this file.
00001 /*
00002  *  red_stellar system.C: reduce some usefull 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 creterium, mass, luminosity, number of stars.
00013  *     -l:      Lower luminosity limit (see below).
00014  *     -n:      Number of Lagrangian radii bins.
00015  *              Might for some choises be forced.
00016  *     -O:      Output option, what information should be studied.
00017  *     -o:      Output the story with data written in root.
00018  *     -S:      Sort option, on what parameter must information be sorted.
00019  *.............................................................................
00020  *  Conserning the Lower luminosity limit option (-l, see above).
00021  *    Currently this option is only applied to the sorting functions.
00022  *    This means that the binning (using Lagrangian radii) is applied
00023  *    on all cluster members.
00024  *    whether or not this is realistic depends on the application.
00025  *    Consequently, the luminosity cut-off does not affect the
00026  *    Lagrangian radii.
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;  // sorted on this parameter.
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   // Normally all stars with L>l_min are visible.
00139   // bool visible = (star.L_eff>l_min?1:0);
00140 
00141   bool visible = false;
00142   if (star.L_eff>=l_min
00143       && (int)star_type != (int)Inert_Remnant)  // casts added by Steve!!
00144     visible = true;
00145 
00146   // However, remnants are only visible if l_min is very small.
00147   // Neutron stars are intrinsically bright but extreme blue!
00148   // only if l_min==0, all stars are visible.
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 // Determine the potential energy of bi with respect to bj, along
00186 // with bi's nearest neighbor and minimum neighbor distance.
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 // compute_energies: calculate the appropriate color code for particle bi
00206 //                   relative to "particle" bj (usually the root node).
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  *  compute_mean_cod -- Returns the position and velocity of the density
00252  *                      center of an N-body system.
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;                        // 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 << " 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 //  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 
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;                        // weight factor
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     //PRI(4); PRL(density_center);
00345     //PRI(4); PRC(rcore); PRC(ncore); PRL(mcore);
00346 
00347     //place the data in the root dyn-story.
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   //    cerr << "rn_1 = " << bin_param[0] << endl;
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   // return if unresonable input is given.
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     // determine the lagrangian radii.
00407   for (i=0; i<nzones; i++)
00408     bin_percent[i] = lagrangian_radius(i, nzones, binning)*total_number;
00409 
00410     // write the lagrangian parameter to the *dyn story.
00411   char r_n[3];
00412   sprintf(r_n, "rn_");
00413 
00414 
00415     // read back from *dyn the lagrangian parameter.
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     //       cerr << r_n << k+1  << " = " << bin_param[k] << endl;
00431   }
00432 
00433   delete []bin_percent;
00434   
00435   //  if (scale)
00436   //     for (int k=0; k<nzones; k++) 
00437   //     bin_param[k] *= to_pc;
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   // return if unresonable input is given.
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     // determine the lagrangian parameter.
00463   for (i=0; i<nzones; i++)
00464     bin_percent[i] = lagrangian_radius(i, nzones, binning) * m_tot;
00465 
00466     // write the lagrangiant radii to the *dyn story.
00467   char r_n[3];
00468   sprintf(r_n, "rm_");
00469 
00470     // read back from *dyn the lagrangian radii.
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     //       cerr << r_n << k+1  << " = " << bin_param[k] << endl;
00488   }
00489 
00490   delete []bin_percent;
00491 
00492   //  if (scale)
00493   //     for (int k=0; k<nzones; k++) 
00494   //     bin_param[k] *= to_msun;
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   // return if unresonable input is given.
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     // determine the lagrangian parameters.
00520   for (i=0; i<nzones; i++)
00521     bin_percent[i] = lagrangian_radius(i, nzones, binning) * total_lumi;
00522 
00523     // write the lagrangiant parameter to the *dyn story.
00524   char r_n[3];
00525   sprintf(r_n, "rl_");
00526 
00527     // read back from *dyn the lagrangian radii.
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     //       cerr << r_n << k+1  << " = " << table[i-1].sort_param << endl;
00545   }
00546 
00547   delete []bin_percent;
00548 
00549   //  if (scale)
00550   //     for (int k=0; k<nzones; k++) 
00551   //     bin_param[k] *= to_pc;
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])); //arbitrary XY plane.
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     //    if (scale_flag) {
00628     //      v_cum *= to_kms;    
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 // the luminosity limit affects the cumulative luminosity, not the mass!
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 //  compare_radii  --  compare the radii of two particles
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 //  compare_parameters  --  compare parameters of two particles
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   // Use the geometric center if the density center is unknown.
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   // fill table with usefull information.
00969   // note that this part might needs a flattening of the tree.
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         // XXX what about co_core?  Should table remember that? -slevy 010218
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     table[i].type = (stellar_type_summary)1;
01002     table[i].age = table[i].dmass; 
01003     table[i].m_rel = table[i].dmass; 
01004     table[i].m_tot = table[i].dmass; 
01005     table[i].m_core = table[i].dmass; 
01006     table[i].T_eff = table[i].dmass; 
01007     table[i].L_eff = table[i].dmass; 
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     // now the array table is sorted in radius.
01018     // we can do all kind of beautiful things with it.
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   //       put_lagrangian_parameters(b, table,   nzones, n, l_min, binning);
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  *  main  --  driver to use  compute_mass_radii() as a tool
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;             // minimum visible luminosity in Lsun.
01145   int nzones = 10;
01146   bool  c_flag = FALSE;      /* if TRUE: a comment given on command line   */
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     //cerr << "scalings" << to_myear << " "
01213     //                   << to_msun  << " "
01214     //                   << to_rsun  << " "
01215     //                   << to_kms   << endl;
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

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