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