00001
00002
00003 #include "dyn.h"
00004
00005
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
00017
00018
00019
00020
00021
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
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
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;
00068
00069
00070
00071
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
00102
00103
00104
00105
00106
00107
00108
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
00121 }
00122 }
00123 }
00124
00125
00126
00127 qsort((void *)rm_table, (size_t)n, sizeof(rm_pair), compare_radii);
00128
00129
00130
00131
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
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
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
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
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
00208
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
00246
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
00261
00262 if (which == 2) compute_general_mass_radii(b, dc_pos, nl, r_lagr,
00263 m_cutoff, M_cutoff, nonlin, single_fn);
00264
00265
00266
00267 if (which == 3) compute_general_mass_radii(b, dc_pos, nl, r_lagr,
00268 m_cutoff, M_cutoff, nonlin, double_fn);
00269
00270
00271
00272
00273
00274
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
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 local void compute_density(dyn * b,
00312 int k,
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)
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
00331 for_all_daughters(dyn, b, d)
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
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;
00364 story * s = d->get_dyn_story();
00365
00366
00367 local_density[is] = density;
00368 is++;
00369 }
00370
00371 delete neighbor_dist_sq;
00372 }
00373
00374
00375
00376
00377
00378
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
00395 real density = local_density[is++];
00396 real dens2 = density * density;
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;
00429
00430
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
00495
00496
00497
00498
00499
00500
00501
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
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
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
00642
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
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";
00676
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
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
00716
00717
00718
00719
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
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
00763
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
00790
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
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
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
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
00881
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
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
00924
00925 r_tot = r_mean[im] + r_mean[jm];
00926 m_tot = m_mean[im] + m_mean[jm];
00927
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
00959
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 }