Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

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

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