Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

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

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