Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

rcore.C

Go to the documentation of this file.
00001 //  sys_stats.C: Print out various diagnostic statistics on a system.
00002 
00003 #include "dyn.h"
00004 
00005 // cerr << "    [R]: " << Rsun_pc / r_conv_star_to_dyn << " pc\n";
00006 #define Rsun_pc 2.255e-8                 // R_sun/parsec = 6.960e+10/3.086e+18
00007 
00008 #define ALL_i ni = n->get_oldest_daughter(); ni != NULL; \
00009                                              ni = ni->get_younger_sister()
00010 #define j_ABOVE_i nj = ni->get_younger_sister(); nj != NULL; \
00011                                              nj = nj->get_younger_sister()
00012 
00013 
00014 local real conv_v_dyn_to_star(real v, real rf, real tf) {
00015 
00016 //              Internal velocity is km/s
00017 //              Internal size is solar raii
00018 //              Internal time is Myr.
00019 //              km/s to Rsun/Myr
00020 //      real to_Rsun_Myr = cnsts.physics(km_per_s) * cnsts.physics(Myear)
00021 //                     / cnsts.parameters(solar_radius);
00022 
00023       real myear = 3.15e+13;
00024       real km_s = 1.0e+5;
00025       real R_sun = 6.960e+10;
00026       real to_Rsun_Myr = km_s * myear / R_sun;
00027       real to_dyn      = rf/tf;
00028       
00029       return v/(to_Rsun_Myr * to_dyn);
00030    }
00031 
00032 
00033 typedef  struct
00034 {
00035     real  radius;
00036     real  mass;
00037 } rm_pair, *rm_pair_ptr;
00038 
00039 //-----------------------------------------------------------------------------
00040 //  compare_radii  --  compare the radii of two particles
00041 //-----------------------------------------------------------------------------
00042 
00043 local int compare_radii(const void * pi, const void * pj)
00044 {
00045     if (((rm_pair_ptr) pi)->radius > ((rm_pair_ptr) pj)->radius)
00046         return(1);
00047     else if (((rm_pair_ptr)pi)->radius < ((rm_pair_ptr)pj)->radius)
00048         return(-1);
00049     else
00050         return(0);
00051 }
00052 
00053 //-----------------------------------------------------------------------------
00054 //  compute_general_mass_radii  --  Get the massradii for all particles.
00055 //-----------------------------------------------------------------------------
00056 
00057 static real nonlin_masses[9] = {0.005, 0.01, 0.02, 0.05, 0.1,
00058                                 0.25, 0.5, 0.75, 0.9};
00059 
00060 local void compute_general_mass_radii(dyn * b, vector dc_pos, int nzones,
00061                                       real r_lagr[],
00062                                       real m_cutoff, real M_cutoff,
00063                                       bool nonlin = false, 
00064                                       boolfn bf=NULL)
00065 {
00066     if (nzones < 2) return;
00067     if (nonlin && nzones != 10) return;         // Special case
00068 
00069     // Note: nzones specifies the number of radial zones to consider.
00070     //       However, we only store radii corresponding to the nzones-1 
00071     //       interior zone boundaries.
00072 
00073     real* mass_percent = new real[nzones-1];
00074     if (mass_percent == NULL) {
00075         cerr << "compute_general_mass_radii: "
00076              << "not enough memory left for mass_percent\n";
00077         return;
00078     }
00079 
00080     int n = 0;
00081     if (bf == NULL) {
00082       for_all_daughters(dyn, b, bb)
00083         if (bb->get_mass()>=m_cutoff && bb->get_mass()<=M_cutoff)
00084           n++;
00085     }
00086     else {
00087         for_all_daughters(dyn, b, bb)
00088           if (bb->get_mass()>=m_cutoff && bb->get_mass()<=M_cutoff)
00089             if ((*bf)(bb))
00090               n++;
00091     }
00092 
00093     rm_pair_ptr rm_table = new rm_pair[n];
00094 
00095     if (rm_table == NULL) {
00096         cerr << "compute_general_mass_radii: "
00097              << "not enough memory left for rm_table\n" << flush;
00098         return;
00099     }
00100 
00101     // Use the geometric center if the density center is unknown.
00102 
00103     //vector dc_pos = 0;
00104     //if (find_qmatch(b->get_dyn_story(), "density_center_pos")) 
00105     //dc_pos = getvq(b->get_dyn_story(), "density_center_pos");
00106 
00107     // Set up an array of (radius, mass) pairs.  Also find the total
00108     // mass of all nodes under consideration.
00109 
00110     real total_mass = 0;
00111 
00112     int i = 0;
00113     for_all_daughters(dyn, b, bi) {
00114       if (bf == NULL || (*bf)(bi)) {
00115         if (bi->get_mass()>=m_cutoff && bi->get_mass()<=M_cutoff) {
00116           total_mass += bi->get_mass();
00117           rm_table[i].radius = abs(bi->get_pos() - dc_pos);
00118           rm_table[i].mass = bi->get_mass();
00119           i++;
00120 //          PRL(i);
00121         }
00122       }
00123     }   
00124 
00125     // Sort the array by radius.
00126 
00127     qsort((void *)rm_table, (size_t)n, sizeof(rm_pair), compare_radii);
00128 
00129     // Determine Lagrangian radii.
00130 
00131     //    cerr << "Determine Lagrangian radii" << endl;
00132     int k;
00133     for (k = 0; k < nzones-1; k++) {
00134         if (!nonlin) 
00135             mass_percent[k] = ((k + 1) / (real)nzones) * total_mass;
00136         else
00137             mass_percent[k] = nonlin_masses[k] * total_mass;
00138     }
00139 
00140     //    real *rlagr = new real[nzones-1];
00141     real cumulative_mass = 0.0;
00142     i = 0;
00143 
00144 
00145     for (k = 0; k < nzones-1; k++) {
00146 
00147       while (cumulative_mass < mass_percent[k]) {
00148         cumulative_mass += rm_table[i++].mass;
00149       }
00150 
00151       r_lagr[k] = rm_table[i-1].radius;
00152     }
00153 
00154 
00155     // Place the data in the root dyn story.
00156 
00157 #if 0
00158     if (bf == NULL)
00159         putiq(b->get_dyn_story(), "boolfn", 0);
00160     else
00161         putiq(b->get_dyn_story(), "boolfn", 1);
00162 
00163     putiq(b->get_dyn_story(), "n_nodes", n);
00164 
00165     putiq(b->get_dyn_story(), "n_lagr", nzones-1);
00166     putra(b->get_dyn_story(), "r_lagr", rlagr, nzones-1);
00167 #endif
00168 
00169     delete mass_percent;
00170     delete rm_table;
00171 //    delete rlagr;
00172     
00173     for (k = 0; k < nzones-1; k ++) 
00174       cerr << " " << b->get_starbase()->conv_r_dyn_to_star(r_lagr[k])
00175                      * Rsun_pc;
00176     cerr << " [pc]" << endl;
00177     
00178 }
00179 
00180 // Convenient synonyms:
00181 
00182 local void  compute_mass_radii_quartiles(dyn * b, vector dc_pos,
00183                                          real m_cutoff, real M_cutoff)
00184 {
00185   int nl = 4;
00186   real *r_lagr = new real[nl-1];
00187   for (int i=0; i<nl-1; i++)
00188     r_lagr[i] = 0;
00189 
00190     compute_general_mass_radii(b, dc_pos, nl, r_lagr, m_cutoff, M_cutoff);
00191 }
00192 
00193 local void  compute_mass_radii_percentiles(dyn * b, vector dc_pos,
00194                                            real m_cutoff, real M_cutoff)
00195 {
00196   int nl = 10;
00197   real *r_lagr = new real[nl-1];
00198   for (int i=0; i<nl-1; i++)
00199     r_lagr[i] = 0;
00200   
00201     compute_general_mass_radii(b, dc_pos, nl, r_lagr, m_cutoff, M_cutoff);
00202 }
00203 
00204 local bool single_fn(dyn * b)
00205 {
00206 
00207   //  int test = getiq(b->get_log_story(), "mass_doubled");
00208   //  PRL(test);
00209   if (getiq(b->get_log_story(), "mass_doubled") == 0 )
00210     return true;
00211   else
00212     return false;
00213 }
00214 
00215 local bool double_fn(dyn * b)
00216 {
00217   if (getiq(b->get_log_story(), "mass_doubled") == 1 )
00218     return true;
00219   else
00220     return false;
00221 }  
00222 
00223 local void print_lagrangian_radii(dyn* b, vector dc_pos, int which_lagr,
00224                                   real m_cutoff, real M_cutoff,
00225                                   int which = 0)
00226 {
00227     bool nonlin = false;
00228 
00229     int nl=0, indent=0;
00230     if (which_lagr == 0) {
00231         nl = 4;
00232         indent = 15;
00233         PRI(4); cerr << "quartiles: ";
00234     } else if (which_lagr == 1) {
00235         nl = 10;
00236         indent = 20;
00237         PRI(4); cerr << "10-percentiles: ";
00238     } else {
00239         nl = 10;
00240         indent = 26;
00241         PRI(4); cerr << "selected percentiles: ";
00242         nonlin = true;
00243     }
00244     
00245     //cerr << "before testnode call" << endl;
00246     //    if (which != 2 || 3) compute_general_mass_radii(b, nl, nonlin, testnode);
00247 
00248     real* r_lagr = new real[nl-1];
00249     if (r_lagr==NULL) {
00250       cerr << "print_lagrangian_radii not enough memory to allocate "
00251            << "r_lagr[" << nl-1<< "]" << endl;
00252       return;
00253     }
00254     for (int i=0; i<nl-1; i++)
00255       r_lagr[i] = 0;
00256     
00257     if (which == 0) compute_general_mass_radii(b, dc_pos, nl, r_lagr,
00258                                                m_cutoff, M_cutoff, nonlin); 
00259 
00260     //    cerr << "before single_fn call" << endl;
00261     //    PRL(which);
00262     if (which == 2) compute_general_mass_radii(b, dc_pos, nl, r_lagr,
00263                                                m_cutoff, M_cutoff, nonlin, single_fn);
00264 
00265     //     cerr << "before double_fn call" << endl;
00266     //    PRL(which);
00267     if (which == 3) compute_general_mass_radii(b, dc_pos, nl, r_lagr,
00268                                                m_cutoff, M_cutoff, nonlin, double_fn);
00269 
00270     //    PRC(dc_pos);PRC(m_cutoff);PRC(M_cutoff);PRL(which);
00271 
00272     //for (int k = 0; k < nl; k ++) 
00273     // cerr << " " << r_lagr[k];
00274     //cerr <<endl;
00275 
00276 #if 0
00277     if (find_qmatch(b->get_dyn_story(), "n_lagr")) {
00278         int n_lagr = getiq(b->get_dyn_story(), "n_lagr");
00279         getra(b->get_dyn_story(), "r_lagr", r_lagr, n_lagr);
00280 
00281         for (int k = 0; k < n_lagr; k += 5) {
00282           if (k > 0) {
00283             cerr << endl;
00284             for (int kk = 0; kk < indent; kk++) cerr << " ";
00285           }
00286           for (int i = k; i < k+5 && i < n_lagr; i++)
00287             cerr << " " << r_lagr[i];
00288         }
00289         cerr << endl;
00290     }
00291 #endif
00292     
00293     delete r_lagr;
00294 }
00295 
00296 /*-----------------------------------------------------------------------------
00297  *  compute_density  --  Get the density for all particles.
00298  *               note:
00299  *                    the neighbor_dist_sq[q] array will contain the distances
00300  *                    to the q-th nearest neighbor (in the form of the squares 
00301  *                    thereof); therefore  neighbor_dist_sq[0] = 0.0  since
00302  *                    this indicates the distance of a particle to itself.
00303  *                    Including this trivial case simplifies the algorithm
00304  *                    below by making it more homogeneous.
00305  *-----------------------------------------------------------------------------
00306  *              Litt.:
00307  *                    Stefano Casertano and Piet Hut: Astroph.J. 298,80 (1985).
00308  *                    To use their recipe, k >= 2 is required.
00309  *-----------------------------------------------------------------------------
00310  */
00311 local void  compute_density(dyn * b,    /* pointer to an Nbody system */
00312                             int k,      /* use kth nearest neighbor */
00313                             int n,
00314                             real local_density[],
00315                             real m_cutoff,
00316                             real M_cutoff)
00317 {
00318     int  q, r, is = 0;
00319     real *neighbor_dist_sq;
00320     real  volume;
00321     real  delr_sq;
00322     
00323     if (k >= n)                           /* no k-th nearest neighbor exists */
00324         cerr << "compute_density: k = " << k << " >= n = " << n << endl;
00325     if (k <= 1)
00326         cerr << "compute_density: k = " << k << " <= 1" << endl;
00327 
00328     neighbor_dist_sq = new real[k+1];
00329 
00330     //  for_all_leaves(dyn, b, d)               // The density is now defined
00331     for_all_daughters(dyn, b, d)        // ONLY for top-level nodes.
00332       if (d->get_mass()>=m_cutoff && d->get_mass()<=M_cutoff)
00333         {
00334         neighbor_dist_sq[0] = 0.0;
00335         for (q = 1; q <= k; q++)
00336             neighbor_dist_sq[q] = VERY_LARGE_NUMBER;
00337 
00338         //      for_all_leaves(dyn, b, dd)
00339         for_all_daughters(dyn, b, dd)
00340           if (dd->get_mass()>=m_cutoff && dd->get_mass()<=M_cutoff)
00341             {
00342             if (d == dd)
00343                 continue;
00344 
00345             delr_sq = square(something_relative_to_root(d, &dyn::get_pos)
00346                              - something_relative_to_root(dd, &dyn::get_pos));
00347 
00348             if (delr_sq < neighbor_dist_sq[k])
00349                 for (q = k-1; q >= 0; q--)
00350                     {
00351                     if (delr_sq > neighbor_dist_sq[q])
00352                         {
00353                         for (r = k; r > q+1; r--)
00354                             neighbor_dist_sq[r] = neighbor_dist_sq[r-1];
00355                         neighbor_dist_sq[q+1] = delr_sq;
00356                         break;
00357                         }
00358                     }
00359             }
00360             
00361         volume = (4.0/3.0) * PI * pow(neighbor_dist_sq[k], 1.5);
00362 
00363         real density =  (k - 1) / volume;           /* Ap. J. 298, 80 (1985) */
00364         story * s = d->get_dyn_story();
00365         //        putiq(s, "density_k_level", k);
00366         //        putrq(s, "density", density);
00367         local_density[is] = density;
00368         is++;
00369         }
00370 
00371     delete neighbor_dist_sq;
00372 }
00373 
00374 
00375 
00376 /*-----------------------------------------------------------------------------
00377  *  compute_mean_cod -- Returns the position and velocity of the density
00378  *                      center of an N-body system.
00379  *-----------------------------------------------------------------------------
00380  */
00381 local void compute_mean_cod(dyn *b,
00382                             real local_density[],
00383                             vector& pos, vector& vel, real m_cutoff,
00384                             real M_cutoff)
00385 {
00386     real total_weight = 0;
00387     pos = 0;
00388     vel = 0;
00389     int is=0;
00390     
00391     for_all_daughters(dyn, b, d) 
00392       if (d->get_mass()>=m_cutoff && d->get_mass()<=M_cutoff) {
00393             
00394         //      real density = getrq(d->get_dyn_story(), "density");
00395         real density = local_density[is++];
00396         real dens2 = density * density;        // weight factor
00397 
00398         total_weight += dens2;
00399         pos += dens2 * d->get_pos();
00400         vel += dens2 * d->get_vel();
00401     }   
00402 
00403     pos /= total_weight;
00404     vel /= total_weight;
00405 }
00406 
00407 /*===========================================================================*/
00408 
00409 local void compute_core_parameters(dyn* b, int k, vector& center,
00410                                    real& rcore, int& ncore, real& mcore,
00411                                    real & vcore, int n,
00412                                    real local_density[], 
00413                                    real m_cutoff, real M_cutoff)
00414 {
00415     vector vel;
00416     int is=0;
00417 
00418     real rcore2 = 0;
00419     if (rcore<=0) {
00420       compute_density(b, k, n, local_density, m_cutoff, M_cutoff);
00421       compute_mean_cod(b, local_density, center, vel, m_cutoff, M_cutoff);
00422 
00423       real total_weight = 0;
00424       real sum = 0;
00425       for_all_daughters(dyn, b, bi) 
00426         if (bi->get_mass()>=m_cutoff && bi->get_mass()<=M_cutoff) {
00427           real density = local_density[is++];
00428           real dens2 = density * density;        // weight factor
00429           //real density = getrq(bi->get_dyn_story(), "density");
00430           //real dens2 = density * density;              // weight factor
00431 
00432           total_weight += dens2;
00433           sum += dens2 * square(bi->get_pos() - center);
00434         }
00435 
00436       rcore2 = sum/total_weight;
00437       rcore = sqrt(rcore2);
00438     }
00439     else
00440       rcore2 = square(rcore);
00441 
00442     ncore = 0;
00443     mcore = 0;
00444     vcore = 0;
00445 
00446     for_all_daughters(dyn, b, bj)
00447       if (bj->get_mass()>=m_cutoff && bj->get_mass()<=M_cutoff) 
00448         if (square(bj->get_pos() - center) <= rcore2) {
00449             ncore++;
00450             mcore += bj->get_mass();
00451             vcore += bj->get_vel()*bj->get_vel();
00452         }
00453     mcore = mcore/(1.0*ncore);
00454     vcore = sqrt(vcore)/(1.0*ncore);
00455 }
00456 
00457 local void print_core_parameters(dyn* b, vector& density_center, real& rcore,
00458                                  int & ncore, real & vcore,
00459                                  int n, real local_density[],
00460                                  real m_cutoff, real M_cutoff,
00461                                  bool verbose)
00462   {
00463     real mcore;
00464 
00465     compute_core_parameters(b, 6, density_center, rcore, ncore, mcore,
00466                             vcore, n, local_density,
00467                             m_cutoff, M_cutoff);
00468 
00469     real r_density_center = sqrt(density_center*density_center);
00470 
00471     vcore = conv_v_dyn_to_star(vcore,
00472                                b->get_starbase()->conv_r_star_to_dyn(1),
00473                                b->get_starbase()->conv_t_star_to_dyn(1));
00474     if (verbose) {
00475 
00476       real M_lower = b->get_starbase()->conv_m_dyn_to_star(m_cutoff);
00477       real M_upper = b->get_starbase()->conv_m_dyn_to_star(M_cutoff);
00478 
00479       cerr << "n = " << n << ", M (lower/upper) = ( "
00480                           << M_lower << ",  " << M_upper << " ) [Msun]\n";
00481       cerr << "     Core: (N, R, m, v) = ( " << ncore << ", "
00482            << Rsun_pc * b->get_starbase()->conv_r_dyn_to_star(rcore)
00483            << ", "  
00484            << b->get_starbase()->conv_m_dyn_to_star(mcore) <<", "
00485            << vcore
00486            << " ) [solar/km/s]\n";
00487       cerr << "     R_to_density_center = "
00488            << Rsun_pc *
00489               b->get_starbase()->conv_r_dyn_to_star(r_density_center)
00490            << " [pc]\n";
00491       
00492 
00493       /*
00494       //place the data in the root dyn-story.
00495       putiq(b->get_dyn_story(), "n_cutoff", n);
00496       putrq(b->get_dyn_story(), "m_cutoff", m_cutoff);
00497       putrq(b->get_dyn_story(), "M_cutoff", M_cutoff);
00498       putvq(b->get_dyn_story(), "density_center_pos", density_center);
00499       putrq(b->get_dyn_story(), "core_radius", rcore);
00500       putiq(b->get_dyn_story(), "n_core", ncore);
00501       putrq(b->get_dyn_story(), "m_core", mcore);
00502       */
00503     }
00504     else {
00505               PRC(n); PRC(m_cutoff); PRL(M_cutoff);
00506       PRI(4); PRC(rcore); PRC(ncore); PRL(mcore);
00507       PRI(4); PRL(r_density_center);
00508     }
00509         
00510 }
00511 
00512 local real system_energy(dyn* b, real m_cutoff, real M_cutoff)
00513 {
00514     real kin = 0;
00515     for_all_leaves(dyn, b, bj)
00516       if (bj->get_mass()>=m_cutoff && bj->get_mass()<=M_cutoff)
00517         kin += bj->get_mass()
00518              * square(something_relative_to_root(bj, &dyn::get_vel));
00519     kin *= 0.5;
00520 
00521     real pot = 0.0;
00522     for_all_leaves(dyn, b, bi) 
00523       if (bi->get_mass()>=m_cutoff && bi->get_mass()<=M_cutoff) {
00524         real dpot = 0.0;
00525         for_all_leaves(dyn, b, bj) 
00526           if (bj->get_mass()>=m_cutoff && bj->get_mass()<=M_cutoff) {
00527             if (bj == bi) break;
00528             vector dx = something_relative_to_root(bi, &dyn::get_pos)
00529                           - something_relative_to_root(bj, &dyn::get_pos);
00530             dpot += bj->get_mass() / abs(dx);
00531         }
00532         pot -= bi->get_mass() * dpot;
00533     }
00534 
00535     return kin + pot;
00536 }
00537 
00538 local void get_energies(dyn * n, real eps2, 
00539                   real& kinetic_energy, real& potential_energy,
00540                   real m_cutoff, real M_cutoff)
00541 {
00542     dyn  * ni, *nj;
00543 
00544     kinetic_energy = 0;
00545     for (ALL_i) 
00546       if (ni->get_mass()>=m_cutoff && ni->get_mass()<=M_cutoff) {
00547       
00548         vector v = ni->get_vel();
00549         kinetic_energy += ni->get_mass() * v * v;
00550     }
00551     kinetic_energy *= 0.5;
00552 
00553     potential_energy = 0;
00554     for (ALL_i) 
00555       if (ni->get_mass()>=m_cutoff && ni->get_mass()<=M_cutoff) {
00556         real dphi = 0;
00557         vector xi = ni->get_pos();
00558         for (j_ABOVE_i) 
00559           if (nj->get_mass()>=m_cutoff && nj->get_mass()<=M_cutoff) {
00560             vector xij = nj->get_pos() - xi;
00561             dphi += nj->get_mass()/sqrt(xij*xij + eps2);
00562         }
00563         potential_energy -= ni->get_mass() * dphi;
00564     }
00565 }
00566 
00567 
00568 local void print_energies(dyn* b, real& kT, real m_cutoff, real M_cutoff, bool verbose)
00569 {
00570     // Energies (top-level nodes):
00571 
00572     real kinetic_energy, potential_energy;
00573     get_energies(b, 0.0, kinetic_energy, potential_energy, m_cutoff, M_cutoff);
00574 
00575     real total_energy = kinetic_energy + potential_energy;
00576     real virial_ratio = -kinetic_energy / potential_energy;
00577     kT = -total_energy / (1.5*b->n_daughters());
00578 
00579     if (verbose) {
00580       PRI(4); cerr << "top-level nodes:\n";
00581       PRI(8); PRC(kinetic_energy); PRL(potential_energy);
00582       PRI(8); PRC(total_energy); PRC(kT); PRL(virial_ratio);
00583 
00584       PRI(4); cerr << "total energy (full system) = "
00585                    << system_energy(b, m_cutoff, M_cutoff) << endl;
00586     }
00587     else
00588       cerr <<"\t"<< kinetic_energy <<" "<< potential_energy
00589            <<" "<< total_energy <<" "<< kT
00590            <<" "<< virial_ratio <<" "<< system_energy(b, m_cutoff, M_cutoff) << endl;
00591 }
00592 
00593 local void print_relaxation_time(dyn* b, real m_cutoff, real M_cutoff, bool verbose)
00594 {
00595     // Print the relaxation time
00596 
00597     real potential_energy, kinetic_energy;
00598     real r_virial, t_relax;
00599     real total_mass = 0;
00600 
00601     int n=0;
00602     for_all_leaves(dyn, b, bj) 
00603       if (bj->get_mass()>=m_cutoff && bj->get_mass()<=M_cutoff) {
00604         n++;
00605         total_mass += bj->get_mass();
00606     }
00607 
00608     get_energies(b, 0.0, kinetic_energy, potential_energy, m_cutoff, M_cutoff);
00609 
00610     r_virial = -0.5 * total_mass * total_mass / potential_energy;
00611 
00612     t_relax = 9.62e-2 * sqrt(r_virial * r_virial * r_virial / total_mass)
00613               * n / log10(0.4 * n);
00614 
00615     if (verbose) {
00616       PRI(4); cerr << "r_virial = "
00617                    << Rsun_pc *
00618                       b->get_starbase()->conv_r_dyn_to_star(r_virial) << endl;
00619       PRI(4); cerr << "t_relax = "
00620                    <<  b->get_starbase()->conv_t_dyn_to_star(t_relax)  << endl;
00621     }
00622     else
00623       cerr <<"\t"<< r_virial <<" "<< t_relax << endl;
00624 }
00625 
00626 local void get_composition(dyn* b,
00627                            real m_cutoff, real M_cutoff,
00628                            int& n, real& mmean,
00629                            real& rmean,
00630                            real& vdisp) {
00631   
00632   n=0;
00633   real T_eff, L_eff, R_eff;
00634   real m_total=0, v2_disp=0, r_total=0;
00635   
00636   for_all_daughters(dyn, b, bi)
00637     if (bi->get_mass()>=m_cutoff && bi->get_mass()<=M_cutoff) {
00638       n++;
00639       m_total += bi->get_mass();
00640       v2_disp += bi->get_vel()*bi->get_vel();
00641       //R_eff = getrq(bi->get_star_story(), "R_eff");
00642       //if (R_eff<=0) {
00643 
00644       T_eff = getrq(bi->get_star_story(), "T_eff");
00645       L_eff = getrq(bi->get_star_story(), "L_eff");
00646       R_eff = sqrt(max(0.1, (1130.*L_eff)/pow(T_eff, 4)));
00647             
00648       r_total += R_eff;
00649     }
00650 
00651   if (n>0) {
00652     mmean = b->get_starbase()->conv_m_dyn_to_star(m_total)/(1.0*n);
00653     rmean = r_total/(1.0*n);
00654 
00655     vdisp = sqrt(v2_disp)/(1.0*n);
00656     vdisp = conv_v_dyn_to_star(vdisp,
00657                                b->get_starbase()->conv_r_star_to_dyn(1),
00658                                b->get_starbase()->conv_t_star_to_dyn(1));
00659   }
00660   
00661 }
00662 //#else
00663 
00664 main(int argc, char **argv)
00665 {
00666     bool binaries = true, verbose = true, out = false,
00667          calc_e = true, Mcut=true, mcut=true;
00668     int nzones = 10;
00669     bool auto_detect = false;
00670     real m_min = 0.1;
00671     real m_max = 100;
00672 
00673     extern char *poptarg;
00674     int c;
00675     char* param_string = "n:Mmeov";     // Note: "v" removed because only the
00676                                         // "verbose" option currently works.
00677 
00678     while ((c = pgetopt(argc, argv, param_string)) != -1)
00679         switch(c) {
00680 
00681             case 'e': calc_e = !calc_e;
00682                       break;
00683             case 'n': nzones = atoi(poptarg);
00684                       break;
00685             case 'M': Mcut = !Mcut;
00686                       break;
00687             case 'm': mcut = !mcut;
00688                       break;
00689             case 'a': auto_detect = !auto_detect;
00690                       break;
00691             case 'o': out = !out;
00692                       break;
00693             case 'v': verbose = !verbose;
00694                       break;
00695             case '?': params_to_usage(cerr, argv[0], param_string);
00696                       exit(1);
00697         }
00698 
00699     // Loop over input until no more data remain.
00700 
00701     dyn *b;
00702 
00703     real to_volume = 4*PI/3.;
00704     real n_rho1, n_rhoi, n_rhoj;
00705     real r_tot, m_tot, v_rel;      
00706     int n, ncore;
00707     real mass_int;
00708     vector density_center;
00709     real rcore=0, vcore=0;
00710     real kT;
00711     real M_cutoff, m_cutoff;
00712     real m_total;
00713 
00714     real mmean, rmean, vdisp;
00715     //     real *core_radius = (real *) calloc(nzones+1, 8);
00716     //     int  *nstars = (int *) calloc(nzones+1, 4);
00717     //     real *m_mean = (real *) calloc(nzones+1, 8);
00718     //     real *v_disp = (real *) calloc(nzones+1, 8);
00719     //     real *r_mean = (real *) calloc(nzones+1, 8);
00720     
00721     real *core_radius = new real[nzones+1];
00722     int  *ncstars = new int[nzones+1];
00723     int  *nstars = new int[nzones+1];
00724     real *m_mean = new real[nzones+1];
00725     real *v_disp = new real[nzones+1];
00726     real *vc_disp = new real[nzones+1];
00727     real *r_mean = new real[nzones+1];
00728         
00729     real geometric, grav_foc, encounter_rate, total_rate;
00730     
00731     while (b = get_dyn(cin)) {
00732 
00733       total_rate = rcore = vcore=0;
00734       
00735       for (int i=0; i<=nzones; i++) {
00736         core_radius[i] = m_mean[i] = v_disp[i] = vc_disp[i] = r_mean[i] = 0;
00737         ncstars[i] = nstars[i] = 0;
00738       }
00739 
00740       b->get_starbase()->print_stellar_evolution_scaling(cerr);
00741       cerr << "Time = " << b->get_system_time() << endl;
00742       
00743       // Count stars and find mass extremes.
00744       n=0;
00745       if (auto_detect) {
00746         m_min = VERY_LARGE_NUMBER;
00747         m_max = -m_min;
00748         for_all_daughters(dyn, b, bi) {
00749           n++;
00750           m_min = min(m_min, bi->get_mass());
00751           m_max = max(m_max, bi->get_mass());
00752         }
00753       }
00754       else {
00755         for_all_daughters(dyn, b, bi) 
00756           n++;
00757         m_min = b->get_starbase()->conv_m_star_to_dyn(m_min);
00758         m_max = b->get_starbase()->conv_m_star_to_dyn(m_max);
00759       }
00760       mass_int = (log10(m_max)-log10(m_min))/(1.0*nzones-1);
00761 
00762       //rcore = getrq(b->get_dyn_story(), "core_radius");
00763       //density_center = getrq(b->get_dyn_story(), "density_center_pos");
00764       
00765       real* local_density = new real[n+1];
00766       if(local_density==NULL) {
00767         cerr << "Not enough memory to allocate local_density[" << n << "].\n";
00768         exit(1);
00769       }
00770       for(int i=0; i<n; i++)
00771         local_density[i] = 0;
00772 
00773       print_core_parameters(b, density_center, rcore, ncore, vcore,
00774                             n, local_density, m_min, m_max, verbose);
00775       print_energies(b, kT, m_min, m_max, verbose);
00776       print_relaxation_time(b, m_min, m_max, verbose);
00777       print_lagrangian_radii(b, density_center, 0, m_min, m_max, 0);
00778 
00779       core_radius[0] = Rsun_pc * b->get_starbase()->conv_r_dyn_to_star(rcore);
00780       nstars[0] = n;
00781       ncstars[0] = ncore;
00782       vc_disp[0] = vcore;
00783 
00784       get_composition(b, m_min, m_max, n, mmean, rmean, vdisp);
00785       m_mean[0] = mmean;
00786       v_disp[0] = vdisp;
00787       r_mean[0] = rmean;
00788       
00789       //PRC(nstars[0]);PRC(m_min);PRC(m_max);PRL(mass_int);
00790       //PRC(rcore);PRC(m_mean[0]);PRC(r_mean[0]);PRC(v_disp[0]);
00791 
00792       for (int i=0; i<nzones; i++) {
00793 
00794         m_cutoff = pow(10., log10(m_min)+i*mass_int);
00795         M_cutoff = pow(10., log10(m_min)+(i+1)*mass_int);
00796 
00797         if (!Mcut) M_cutoff = m_max;
00798         if (!mcut) m_cutoff = m_min;
00799 
00800         for(int is=0; is<nstars[0]; is++)
00801           local_density[is] = 0;
00802 
00803         mmean = vdisp = rmean = 0;
00804         get_composition(b, m_cutoff, M_cutoff, n, mmean, rmean, vdisp); 
00805         nstars[i+1] = n;
00806         m_mean[i+1] = mmean;
00807         v_disp[i+1] = vdisp;
00808         r_mean[i+1] = rmean;
00809         
00810         if (n > 6 &&
00811             !(n==nstars[i] && (!Mcut || !mcut))) {
00812 
00813           rcore = 0;
00814           print_core_parameters(b, density_center, rcore, ncore, vcore,
00815                                 n, local_density, m_cutoff, M_cutoff, verbose);
00816           core_radius[i+1] = Rsun_pc * b->get_starbase()
00817                                         ->conv_r_dyn_to_star(rcore);
00818           ncstars[i+1] = ncore;
00819           vc_disp[i+1] = vcore;
00820 
00821           print_energies(b, kT, m_cutoff, M_cutoff, verbose);
00822           print_relaxation_time(b, m_cutoff, M_cutoff, verbose);
00823           print_lagrangian_radii(b, density_center, 0, m_cutoff, M_cutoff, 0);
00824 
00825           //PRC(n);PRC(core_radius[0]);PRL(core_radius[i+1]);
00826 
00827           n_rho1 = 1./(to_volume * pow(core_radius[0], 3));
00828           n_rhoi = ncstars[i+1]/(to_volume * pow(core_radius[i+1], 3));
00829           r_tot  = r_mean[0] + r_mean[i+1];
00830           m_tot  = m_mean[0] + m_mean[i+1];
00831           v_rel  = sqrt(pow(vc_disp[0], 2) + pow(vc_disp[i+1], 2));
00832 
00833           //PRC(vc_disp[0]);PRC(vc_disp[i+1]);PRL(v_rel);
00834           
00835           geometric = 6.31e-9 * v_rel * pow(r_tot, 2);
00836           grav_foc = 3.61e-3 * m_tot * r_tot / v_rel;
00837           encounter_rate = (n_rho1/1000.) * (n_rhoi/1000)
00838                          * pow(core_radius[0], 3)
00839                          * (grav_foc + geometric);
00840 
00841           if (verbose) {
00842             cerr << "     Stars: (N, r, m, v) = ( "
00843                  << nstars[i+1] <<", "
00844                  << r_mean[i+1] <<", "
00845                  << m_mean[i+1] <<", "
00846                  << v_disp[i+1] <<" ) [solar/km/s]\n";
00847             cerr << "     encounter_rate = "
00848                  << encounter_rate << " [per Myr]\n"
00849                  << "          (geo, gf) = ( "
00850                  << 100 * geometric/(geometric+grav_foc)
00851                  << ", " << 100 * grav_foc/(geometric+grav_foc)
00852                  << " ) [\%]\n\n";
00853           }
00854           else {
00855             PRI(4); PRC(m_mean[i+1]);PRC(v_disp[i+1]);PRL(r_mean[i+1]);
00856             PRI(4);PRC(geometric); PRL(grav_foc);
00857             PRI(4);PRL(encounter_rate);
00858             cerr << endl;
00859 
00860           }
00861 
00862         }
00863       }
00864       
00865       // Now print the encounter probability in a mass-mass plane.
00866       cerr << log10(b->get_starbase()
00867                      ->conv_m_dyn_to_star(m_min)) <<" "
00868            << log10(b->get_starbase()
00869                      ->conv_m_dyn_to_star(m_max)) << " "
00870            << nzones << endl;
00871       cerr << log10(b->get_starbase()
00872                      ->conv_m_dyn_to_star(m_min)) <<" "
00873            << log10(b->get_starbase()
00874                      ->conv_m_dyn_to_star(m_max)) << " "
00875            << nzones << endl;
00876       
00877       for (int im=1; im<nzones+1; im++) {
00878         for (int jm=im; jm<nzones+1; jm++) {
00879 
00880           //PRC(im);PRC(jm);PRC(nstars[im]);PRL(nstars[jm]);
00881           //PRC(core_radius[0]);PRC(core_radius[im]);PRL(core_radius[jm]);
00882             
00883           if (core_radius[im]>0 && core_radius[jm]>0) {
00884 
00885 
00886             n_rhoi = 1./(to_volume * pow(core_radius[im], 3));
00887             n_rhoj = 1./(to_volume * pow(core_radius[jm], 3));
00888             r_tot  = r_mean[im] + r_mean[jm];
00889             m_tot  = m_mean[im] + m_mean[jm];
00890             v_rel  = sqrt(pow(vc_disp[im], 2) + pow(vc_disp[jm], 2));
00891 
00892             rcore = min(core_radius[im], core_radius[jm]);
00893 
00894             //PRC(vc_disp[im]);PRC(vc_disp[jm]);PRL(v_rel);
00895 
00896             geometric = 6.31e-15 * v_rel * pow(r_tot, 2);
00897             grav_foc = 3.61e-9 * m_tot * r_tot / v_rel;
00898 
00899             if (im==jm) 
00900               encounter_rate = 0.5 * ((ncstars[im]-1) * n_rhoi)
00901                                    *  (ncstars[jm] * n_rhoj)
00902                              * pow(rcore, 3)
00903                              * (grav_foc + geometric);
00904             else
00905               encounter_rate = (ncstars[im] * n_rhoi)
00906                              * (ncstars[jm] * n_rhoj)
00907                              * pow(rcore, 3)
00908                              * (grav_foc + geometric);
00909 
00910             cerr << jm <<" "<< im <<" "
00911                  << m_mean[jm] <<" "<< m_mean[im] <<" "
00912                  << ncstars[jm] <<" "<< ncstars[im] <<" "
00913                  << encounter_rate << endl;
00914           }
00915           else if (core_radius[im]>0 || core_radius[jm]>0) {
00916 
00917             real ncore_i = ncstars[im];
00918             real ncore_j = ncstars[jm];
00919             
00920             if (ncstars[im]==0) ncore_i = core_radius[0] * nstars[im];
00921             if (ncstars[jm]==0) ncore_j = core_radius[0] * nstars[jm];
00922             
00923             //n_rhoi = 1./(to_volume * pow(core_radius[0], 3));
00924             //n_rhoj = 1./(to_volume * pow(core_radius[0], 3));
00925             r_tot  = r_mean[im] + r_mean[jm];
00926             m_tot  = m_mean[im] + m_mean[jm];
00927             //v_rel  = sqrt(pow(vc_disp[0], 2) + pow(vc_disp[0], 2));
00928 
00929             if (core_radius[im]>0) {
00930               n_rhoi = 1./(to_volume * pow(core_radius[im], 3));
00931               
00932               if (core_radius[jm]>0) {
00933                 n_rhoj = 1./(to_volume * pow(core_radius[jm], 3));
00934                 rcore = min(core_radius[im], core_radius[jm]);
00935                 v_rel  = sqrt(pow(vc_disp[im], 2) + pow(vc_disp[jm], 2));
00936               }
00937               else {
00938                 n_rhoj = 1./(to_volume * pow(core_radius[0], 3));
00939                 rcore = min(core_radius[im], core_radius[0]);
00940                 v_rel  = sqrt(pow(vc_disp[im], 2) + pow(v_disp[jm], 2));
00941               }
00942             }
00943             else {
00944               n_rhoi = 1./(to_volume * pow(core_radius[0], 3));
00945               
00946               if (core_radius[jm]>0) {
00947                 n_rhoj = 1./(to_volume * pow(core_radius[jm], 3));
00948                 rcore = min(core_radius[0], core_radius[jm]);
00949                 v_rel  = sqrt(pow(v_disp[jm], 2) + pow(vc_disp[jm], 2));
00950               }
00951               else {
00952                 rcore = core_radius[0];
00953                 n_rhoj = 1./(to_volume * pow(rcore, 3));
00954                 v_rel  = sqrt(pow(v_disp[im], 2) + pow(v_disp[jm], 2));
00955               }
00956             }
00957 
00958             //PRC(v_rel);PRC(n_rhoi);PRC(n_rhoj);PRL(rcore);
00959             //PRC(ncore_i);PRL(ncore_j);
00960             
00961             geometric = 6.31e-15 * v_rel * pow(r_tot, 2);
00962             grav_foc = 3.61e-9 * m_tot * r_tot / v_rel;
00963             if (im==jm) {
00964               if (ncore_i>1) 
00965                 encounter_rate = 0.5 * ((ncore_i-1) * n_rhoi)
00966                                      *  (ncore_j * n_rhoj)
00967                                * pow(rcore, 3)
00968                                * (grav_foc + geometric);
00969               else
00970                 encounter_rate = 0;
00971             }
00972             else
00973               encounter_rate = (ncore_i * n_rhoi)
00974                              * (ncore_j * n_rhoj)
00975                              * pow(rcore, 3)
00976                              * (grav_foc + geometric);
00977             
00978             
00979             cerr << jm <<" "<< im <<" "
00980                  << m_mean[jm] <<" "<< m_mean[im] <<" "
00981                  << ncore_j <<" "<< ncore_i <<" "
00982                  << encounter_rate << endl;
00983 
00984           } 
00985 
00986           total_rate += encounter_rate;
00987           cerr << flush;
00988         }
00989       }
00990       cerr << "     Total encounter rate = "
00991            << total_rate << " [per Myr]" << endl;
00992       
00993       cerr << 0 << " " << 0 << " "
00994            << 0 << " " << 0 << " "
00995            << 0 << " " << 0 << " "
00996            << 0 << endl;
00997 
00998       rmtree(b);
00999     }
01000 
01001 
01002 }

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