00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "scatter.h"
00020 #include "kepler.h"
00021
00022 #define UNPERTURBED_DIAG false
00023
00024 void kepler_pair_to_triple(kepler & k1,
00025 kepler & k2,
00026 sdyn * b1,
00027 sdyn * b2,
00028 sdyn * b3)
00029 {
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 real m1 = b1->get_mass();
00041 real m2 = b2->get_mass();
00042 real m3 = b3->get_mass();
00043
00044 real m12 = m1 + m2;
00045 real m123 = m12 + m3;
00046
00047
00048
00049 b3->set_pos(m12 * k2.get_rel_pos() / m123);
00050 b3->set_vel(m12 * k2.get_rel_vel() / m123);
00051
00052 b1->set_pos(-m3 * k2.get_rel_pos() / m123);
00053 b1->set_vel(-m3 * k2.get_rel_vel() / m123);
00054
00055 b2->set_pos(b1->get_pos());
00056 b2->set_vel(b1->get_vel());
00057
00058
00059
00060 b1->inc_pos(-m2 * k1.get_rel_pos() / m12);
00061 b1->inc_vel(-m2 * k1.get_rel_vel() / m12);
00062
00063 b2->inc_pos( m1 * k1.get_rel_pos() / m12);
00064 b2->inc_vel( m1 * k1.get_rel_vel() / m12);
00065
00066 }
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 bool tree_is_unbound(sdyn* root, real ttf, int debug) {
00082
00083 if (debug) {
00084 cerr << "Top level nodes: ";
00085 for_all_daughters(sdyn, root, bb) cerr << " " << id(bb);
00086 cerr << endl;
00087 }
00088
00089
00090 root->to_com();
00091
00092 real kin = 0;
00093 real pot = 0;
00094
00095 for_all_daughters(sdyn, root, bi) {
00096 for (sdyn* bj = bi->get_younger_sister();
00097 bj != NULL; bj = bj->get_younger_sister()) {
00098
00099 if (debug) cerr << "checking i = " << id(bi)
00100 << " j = " << id(bj) << endl;
00101
00102
00103
00104 if ((bi->get_pos() - bj->get_pos())
00105 * (bi->get_vel() - bj->get_vel()) < 0) return FALSE;
00106
00107 real rij = abs(bi->get_pos() - bj->get_pos());
00108
00109 if (debug) cerr << " rij = " << rij << endl;
00110
00111 real mij = bi->get_mass() + bj->get_mass();
00112 real mu_scale = ttf * bi->get_mass() / mij;
00113
00114
00115
00116 real rlimit = max(LARGE_SEPARATION,
00117 bi->get_radius() * pow(mu_scale, -1/3.0));
00118
00119 if (debug) cerr << " rlimit = " << rlimit << endl;
00120
00121 if (rij < rlimit) return FALSE;
00122
00123 real scaled_safety_factor = ENERGY_SAFETY_FACTOR * rlimit / rij;
00124
00125 real kij = 0.5 * square(bi->get_vel() - bj->get_vel());
00126 real pij = mij / rij;
00127 real eij = kij - pij;
00128
00129 if (debug) cerr << " kij = " << kij
00130 << " pij = " << pij
00131 << " eij = " << kij - pij
00132 << endl;
00133
00134 if (eij < 0) return FALSE;
00135 if (abs(kij/pij - 1) < scaled_safety_factor) return FALSE;
00136
00137 real aij = 0.5 * mij / eij;
00138 vector cmij = (bi->get_mass() * bi->get_pos()
00139 + bj->get_mass() * bj->get_pos()) / mij;
00140
00141
00142
00143 for_all_daughters(sdyn, root, bk)
00144 if (bk != bi && bk != bj) {
00145
00146 real rk = abs(bk->get_pos() - cmij);
00147
00148 if (debug) cerr << " checking perturber " << id(bk)
00149 << " at distance " << rk << "...";
00150
00151
00152
00153
00154
00155
00156 if (rk < aij * pow(ttf * mij
00157 / (bk->get_mass() + mij), -1/3.0)) {
00158 if (debug) cerr << "too close" << endl;
00159 return FALSE;
00160 }
00161 if (debug) cerr << endl;
00162 }
00163
00164 if (debug) cerr << " done" << endl;
00165
00166 pot -= bi->get_mass() * bj->get_mass() / rij;
00167 }
00168 kin += 0.5 * bi->get_mass() * square(bi->get_vel());
00169 }
00170
00171
00172
00173
00174
00175 if (kin + pot <= 0) return FALSE;
00176 return TRUE;
00177 }
00178
00179 #if 0
00180
00181 bool tree_is_unbound(sdyn* root, int debug) {
00182
00183 if (debug) {
00184 cerr << "Top level nodes: ";
00185 for_all_daughters(sdyn, root, bb) cerr << " " << id(bb);
00186 cerr << endl;
00187 }
00188
00189 root->to_com();
00190
00191 real kin = 0;
00192 real pot = 0;
00193
00194 for_all_daughters(sdyn, root, bi) {
00195 for (sdyn* bj = bi->get_younger_sister();
00196 bj != NULL; bj = bj->get_younger_sister()) {
00197
00198 if (debug) cerr << "checking i = " << id(bi)
00199 << " j = " << id(bj) << endl;
00200
00201
00202
00203 if ((bi->get_pos() - bj->get_pos())
00204 * (bi->get_vel() - bj->get_vel()) < 0) return FALSE;
00205
00206 real rij = abs(bi->get_pos() - bj->get_pos());
00207
00208 if (debug) cerr << " rij = " << rij << endl;
00209
00210 real mij = bi->get_mass() + bj->get_mass();
00211 real mu_scale = TIDAL_TOL_FACTOR * bi->get_mass() / mij;
00212
00213
00214
00215 real rlimit = max(LARGE_SEPARATION,
00216 bi->get_radius() * pow(mu_scale, -1/3.0));
00217
00218 if (debug) cerr << " rlimit = " << rlimit << endl;
00219
00220 if (rij < rlimit) return FALSE;
00221
00222 real scaled_safety_factor = ENERGY_SAFETY_FACTOR * rlimit / rij;
00223
00224 real kij = 0.5 * square(bi->get_vel() - bj->get_vel());
00225 real pij = mij / rij;
00226 real eij = kij - pij;
00227
00228 if (debug) cerr << " kij = " << kij
00229 << " pij = " << pij
00230 << " eij = " << kij - pij
00231 << endl;
00232
00233 if (eij < 0) return FALSE;
00234 if (abs(kij/pij - 1) < scaled_safety_factor) return FALSE;
00235
00236 real aij = 0.5 * mij / eij;
00237 vector cmij = (bi->get_mass() * bi->get_pos()
00238 + bj->get_mass() * bj->get_pos()) / mij;
00239
00240
00241
00242 for_all_daughters(sdyn, root, bk)
00243 if (bk != bi && bk != bj) {
00244
00245 real rk = abs(bk->get_pos() - cmij);
00246
00247 if (debug) cerr << " checking perturber " << id(bk)
00248 << " at distance " << rk << "...";
00249
00250 if (rk < aij * pow(TIDAL_TOL_FACTOR * mij
00251 / (bk->get_mass() + mij), -1/3.0)) {
00252 if (debug) cerr << "too close" << endl;
00253 return FALSE;
00254 }
00255 if (debug) cerr << endl;
00256 }
00257
00258 if (debug) cerr << " done" << endl;
00259
00260 pot -= bi->get_mass() * bj->get_mass() / rij;
00261 }
00262 kin += 0.5 * bi->get_mass() * square(bi->get_vel());
00263 }
00264
00265
00266
00267
00268
00269 if (kin + pot <= 0) return FALSE;
00270 return TRUE;
00271 }
00272 #endif
00273
00274 local real potential_energy(sdyn * b) {
00275
00276 real u = 0;
00277
00278 for_all_daughters(sdyn, b, bi) {
00279 for (sdyn * bj = bi->get_younger_sister(); bj != NULL;
00280 bj = bj->get_younger_sister())
00281 u -= bi->get_mass() * bj->get_mass()
00282 / abs(bi->get_pos() - bj->get_pos());
00283 }
00284
00285 return u;
00286 }
00287
00288 local real energy(sdyn * b)
00289 {
00290 real k = 0, u = 0, dissipation = 0;
00291
00292 for_all_daughters(sdyn, b, bi) {
00293
00294
00295
00296 k += bi->get_mass() * bi->get_vel() * bi->get_vel();
00297 dissipation += bi->get_energy_dissipation();
00298
00299 for (sdyn * bj = bi->get_younger_sister(); bj != NULL;
00300 bj = bj->get_younger_sister()) {
00301
00302
00303
00304 u -= bi->get_mass() * bj->get_mass()
00305 / abs(bi->get_pos() - bj->get_pos());
00306 }
00307 }
00308
00309 return 0.5*k + u + dissipation;
00310 }
00311
00312 void set_kepler_from_sdyn(kepler& k, sdyn* b1, sdyn* b2)
00313 {
00314 if (b1->get_time() != b2->get_time())
00315 err_exit("set_kepler_from_sdyn: inconsistent times");
00316
00317 k.set_time(b1->get_time());
00318 k.set_total_mass( b1->get_mass() + b2->get_mass() );
00319 k.set_rel_pos( b2->get_pos() - b1->get_pos() );
00320 k.set_rel_vel( b2->get_vel() - b1->get_vel() );
00321
00322 k.initialize_from_pos_and_vel();
00323 }
00324
00325
00326 local void stop_integration(sdyn * bi, sdyn * bj, sdyn * bk,
00327 real ejk, real mjk,
00328 real sep, real virial_ratio) {
00329
00330 real ajk = 0.5 * mjk / abs(ejk);
00331
00332
00333
00334
00335 real ang_mom = abs((bk->get_pos() - bj->get_pos())
00336 ^ (bk->get_vel() - bj->get_vel()));
00337
00338 real ecc2 = 1 - ang_mom * ang_mom / (mjk * ajk);
00339
00340 if (ecc2 < 1.e-10) {
00341
00342
00343
00344 kepler k;
00345 set_kepler_from_sdyn(k, bj, bk);
00346
00347
00348 } else
00349
00350 ;
00351
00352
00353
00354
00355
00356 }
00357
00358
00359 local void extend_orbits(sdyn * b1, sdyn * b2, sdyn * b3, real& apo)
00360
00361
00362
00363 {
00364 if ( (b1->get_time() != b2->get_time())
00365 || (b1->get_time() != b3->get_time()) )
00366 err_exit("extend_orbits: inconsistent times");
00367
00368 real time = b3->get_time();
00369
00370 kepler inner, outer;
00371
00372 set_kepler_from_sdyn(inner, b1, b2);
00373
00374 real m1 = b1->get_mass();
00375 real m2 = b2->get_mass();
00376 real m3 = b3->get_mass();
00377 real m12 = m1 + m2;
00378 real m123 = m12 + m3;
00379
00380 outer.set_time(time);
00381 outer.set_total_mass(m123);
00382
00383
00384
00385 vector cmr = (m1 * b1->get_pos() + m2 * b2->get_pos()) / m12;
00386 vector cmv = (m1 * b1->get_vel() + m2 * b2->get_vel()) / m12;
00387
00388 outer.set_rel_pos(b3->get_pos() - cmr);
00389 outer.set_rel_vel(b3->get_vel() - cmv);
00390
00391 outer.initialize_from_pos_and_vel();
00392
00393
00394
00395
00396 apo = outer.get_semi_major_axis() * (1 + outer.get_eccentricity());
00397
00398 if (UNPERTURBED_DIAG) {
00399
00400 cerr << " inner binary: r = " << inner.get_separation()
00401 << " a = " << inner.get_semi_major_axis()
00402 << " e = " << inner.get_eccentricity()
00403 << endl
00404 << " mass = " << inner.get_total_mass() << endl
00405 << " pos = " << inner.get_rel_pos() << endl
00406 << " vel = " << inner.get_rel_vel() << endl;
00407 cerr << " outer binary: R = " << outer.get_separation()
00408 << " a = " << outer.get_semi_major_axis() << endl
00409 << " e = " << outer.get_eccentricity()
00410 << endl
00411 << " mass = " << outer.get_total_mass() << endl
00412 << " pos = " << outer.get_rel_pos() << endl
00413 << " vel = " << outer.get_rel_vel() << endl;
00414
00415 }
00416
00417
00418
00419
00420 real orbits = 2 * (outer.pred_advance_to_apastron() - time)
00421 / inner.get_period();
00422
00423
00424
00425 real big = 1.e9;
00426 while (orbits > big) {
00427 time += big*inner.get_period();
00428 orbits -= big;
00429 }
00430
00431 int inner_orbits = (int) (orbits + 0.5);
00432 time += inner_orbits * inner.get_period();
00433
00434 outer.transform_to_time(time);
00435
00436
00437
00438
00439 inner.set_time(time);
00440
00441 if (UNPERTURBED_DIAG) {
00442
00443 cerr << " outer binary: R = " << outer.get_separation()
00444 << " a = " << outer.get_semi_major_axis() << endl
00445 << " e = " << outer.get_eccentricity()
00446 << endl
00447 << " mass = " << outer.get_total_mass() << endl
00448 << " pos = " << outer.get_rel_pos() << endl
00449 << " vel = " << outer.get_rel_vel() << endl;
00450
00451 }
00452
00453
00454
00455 b1->get_parent()->set_time(time);
00456 b1->set_time(time);
00457 b2->set_time(time);
00458 b3->set_time(time);
00459
00460 kepler_pair_to_triple(inner, outer, b1, b2, b3);
00461
00462
00463
00464
00465
00466
00467
00468 }
00469
00470 local int escape(sdyn * bi, sdyn * bj, sdyn * bk, real ejk,
00471 real ttf) {
00472
00473
00474
00475
00476
00477 if (ejk >= 0) return 0;
00478
00479 real mi = bi->get_mass();
00480 real mj = bj->get_mass();
00481 real mk = bk->get_mass();
00482 real mjk = mj + mk;
00483
00484
00485
00486 vector cmr = (mj * bj->get_pos() + mk * bk->get_pos()) / mjk;
00487 vector cmv = (mj * bj->get_vel() + mk * bk->get_vel()) / mjk;
00488
00489
00490
00491
00492
00493
00494
00495 vector dv = bi->get_vel() - cmv;
00496 vector dr = bi->get_pos() - cmr;
00497
00498
00499
00500
00501
00502
00503 if (dr*dv <= 0) return 0;
00504
00505 real sep = abs(dr);
00506 real virial_ratio = .5 * dv * dv * sep / (mi + mj + mk);
00507
00508
00509
00510
00511
00512 if (dr*dv <= 0) {
00513
00514 cerr << "stopping... \n";
00515 cerr << " sep = " << sep << " dr*dv = " << dr*dv;
00516 cerr << endl;
00517
00518 stop_integration(bi, bj, bk, ejk, mjk, sep, virial_ratio);
00519 return 1;
00520 }
00521
00522
00523
00524 real ajk = 0.5 * mjk / abs(ejk);
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539 real rlimit = (ajk + bi->get_radius())
00540 * pow(ttf * mjk / (mi + mjk), -1/3.0);
00541
00542
00543
00544
00545 if (sep < rlimit) return 0;
00546
00547
00548
00549
00550 real scaled_safety_factor = ENERGY_SAFETY_FACTOR * rlimit / sep;
00551
00552
00553
00554
00555
00556
00557
00558
00559 if (abs(virial_ratio - 1) < scaled_safety_factor) return 0;
00560
00561
00562
00563 if (virial_ratio > 1) {
00564
00565
00566
00567
00568 if (false) {
00569 #if 0
00570
00571 if (bi->get_index() == 1)
00572 final->descriptor = exchange_1;
00573 else if (bi->get_index() == 2)
00574 final->descriptor = exchange_2;
00575 else if (bi->get_index() == 3)
00576 final->descriptor = preservation;
00577 else
00578 final->descriptor = unknown_final;
00579 #endif
00580
00581
00582 real ang_mom = abs((bk->get_pos() - bj->get_pos())
00583 ^ (bk->get_vel() - bj->get_vel()));
00584
00585 real ecc2 = 1 - ang_mom * ang_mom / (mjk * ajk);
00586 if (ecc2 < 1.e-10) {
00587
00588
00589
00590 kepler k;
00591 set_kepler_from_sdyn(k, bj, bk);
00592
00593
00594 } else
00595
00596 ;
00597
00598
00599
00600
00601 }
00602
00603 return 1;
00604
00605 } else {
00606
00607
00608
00609
00610 real e = energy(bi->get_parent());
00611
00612 if (UNPERTURBED_DIAG)
00613 cerr << "Beginning analytic extension at time "
00614 << bi->get_parent()->get_time()
00615 + bi->get_parent()->get_time_offset()
00616 << endl;
00617
00618 real apo;
00619 extend_orbits(bj, bk, bi, apo);
00620
00621
00622
00623 if (UNPERTURBED_DIAG)
00624 cerr << "Done. Energy error = "
00625 << energy(bi->get_parent()) - e
00626 << endl;
00627
00628
00629
00630
00631
00632
00633
00634
00635 }
00636
00637 return 0;
00638 }
00639
00640 #define UNPERTURBED_DIAG false
00641
00642 local void determine_triple_parameters(sdyn * b, real& apo) {
00643
00644 cerr << "determine_triple_parameters" << endl;
00645
00646 sdyn *b1, *b2, *b3;
00647 int i=0;
00648 for_all_leaves(sdyn, b, bi) {
00649 if(i==0) b1 = bi;
00650 else if(i==1) b2 = bi;
00651 else if(i==2) b3 = bi;
00652 i++;
00653 }
00654
00655 if ( (b1->get_time() != b2->get_time())
00656 || (b1->get_time() != b3->get_time()) )
00657 err_exit("extend_orbits: inconsistent times");
00658
00659 real time = b3->get_time();
00660
00661 kepler inner, outer;
00662
00663 set_kepler_from_sdyn(inner, b1, b2);
00664
00665 real m1 = b1->get_mass();
00666 real m2 = b2->get_mass();
00667 real m3 = b3->get_mass();
00668 real m12 = m1 + m2;
00669 real m123 = m12 + m3;
00670
00671 outer.set_time(time);
00672 outer.set_total_mass(m123);
00673
00674
00675
00676 vector cmr = (m1 * b1->get_pos() + m2 * b2->get_pos()) / m12;
00677 vector cmv = (m1 * b1->get_vel() + m2 * b2->get_vel()) / m12;
00678
00679 outer.set_rel_pos(b3->get_pos() - cmr);
00680 outer.set_rel_vel(b3->get_vel() - cmv);
00681
00682 outer.initialize_from_pos_and_vel();
00683
00684
00685
00686
00687 apo = outer.get_semi_major_axis() * (1 + outer.get_eccentricity());
00688
00689 cerr << " inner binary: r = " << inner.get_separation()
00690 << " a = " << inner.get_semi_major_axis()
00691 << " e = " << inner.get_eccentricity()
00692 << endl
00693 << " mass = " << inner.get_total_mass() << endl
00694 << " pos = " << inner.get_rel_pos() << endl
00695 << " vel = " << inner.get_rel_vel() << endl;
00696 cerr << " outer binary: R = " << outer.get_separation()
00697 << " a = " << outer.get_semi_major_axis() << endl
00698 << " e = " << outer.get_eccentricity()
00699 << endl
00700 << " mass = " << outer.get_total_mass() << endl
00701 << " pos = " << outer.get_rel_pos() << endl
00702 << " vel = " << outer.get_rel_vel() << endl;
00703
00704
00705
00706
00707
00708
00709
00710
00711 }
00712
00713
00714
00715
00716
00717
00718
00719 local int triple_escape(real e12, real r3, real m12, real m3,
00720 real tidal_tol_factor)
00721 {
00722
00723 if (e12 < 0) return 0;
00724
00725 real a12 = 0.5 * m12 / e12;
00726
00727
00728
00729
00730
00731
00732
00733
00734 real tid_fac = tidal_tol_factor * m12 / (m3 + m12);
00735 real ratio = a12/r3;
00736
00737 if (ratio*ratio*ratio > tid_fac)
00738
00739 return 1;
00740 else
00741 return 0;
00742 }
00743
00744 local int extend_or_end_scatter4(sdyn * b) {
00745
00746 b->flatten_node();
00747 b->to_com();
00748 real mt= b->get_mass();
00749
00750 real rij[5], phi[5], mu[5], kij[5], vrij[5];
00751 real mij[5], mkl[5];
00752 sdyn* bj = NULL;
00753
00754 int i=0;
00755 real phit=0;
00756 vector dv;
00757 for_all_leaves(sdyn, b, bi) {
00758 for (bj = (sdyn*)bi->next_node(b); bj != NULL;
00759 bj = (sdyn*)bj->next_node(b)) {
00760
00761 mij[i] = bi->get_mass() + bj->get_mass();
00762 mkl[i] = mt - mij[i];
00763 rij[i] = abs(bi->get_pos() - bj->get_pos());
00764 PRC(rij[i]);PRC(bi->format_label());PRL(bj->format_label());
00765 phi[i] = bi->get_mass() * bj->get_mass() / rij[i];
00766 phit += phi[i];
00767 mu[i] = bi->get_mass() * bj->get_mass() / (mij[i]);
00768
00769 dv = bj->get_vel() - bi->get_vel();
00770 kij[i] = 0.5 * mu[i] * dv * dv;
00771 vrij[i] = dv * (bj->get_pos() - bi->get_pos());
00772
00773 i++;
00774 }
00775 }
00776
00777 i=0;
00778 real m[4], k[4];
00779 real kt=0;
00780 {
00781 for_all_leaves(sdyn, b, bj) {
00782 m[i] = bj->get_mass();
00783 k[i] = 0.5 * m[i] * bj->get_vel() * bj->get_vel();
00784 kt += k[i];
00785 i++;
00786 }}
00787
00788 bool unbound = false;
00789 if (kt >= phit)
00790 unbound = true;
00791
00792 bool large_distance = false;
00793 bool receding = false;
00794 if(!unbound)
00795 for(i=0; i<5; i++) {
00796 if(kij[i]>phi[i]) {
00797 unbound = true;
00798 break;
00799 }
00800 if(rij[i]>LARGE_SEPARATION) {
00801 large_distance = true;
00802 break;
00803 }
00804 if(vrij[i]>0) {
00805 receding = true;
00806 break;
00807 }
00808 }
00809
00810 real rmin;
00811 bool tescape = false;
00812 real ttf = TIDAL_TOL_FACTOR;
00813 for(i=0; i<5; i++) {
00814 rmin = VERY_LARGE_NUMBER;
00815 for(int j=0; j<5; j++)
00816 if(j!=i) rmin = min(rmin, rij[j]);
00817 tescape = triple_escape(kij[i] - phi[i], rmin, mij[i], mkl[i], ttf);
00818 if(tescape) break;
00819 }
00820
00821 PRC(unbound);PRC(large_distance);PRC(receding);PRL(tescape);
00822
00823 if(unbound || large_distance || receding || tescape)
00824 return 0;
00825
00826
00827
00828
00829
00830
00831
00832
00833 #if 0
00834 bool bescape = false;
00835 real rtot;
00836 for(i=0; i<5; i++) {
00837 rtot = 0;
00838 for(j=0; j<5; j++)
00839 if(j!=i) rtot += rij[j];
00840 if (rij[i] * LARGE_SEPARATION_FACTOR < rtot)
00841 bescape = escape(b3, b1, b2, (k12 - phi12)/mu12, ttf);
00842 if(bescape) return 0;
00843 }
00844 #endif
00845
00846 cerr << "Make tree" << flush << endl;
00847 make_tree(b, DYNAMICS, STABILITY, K_MAX, true);
00848 cerr << "tree made" << endl;
00849
00850 return 1;
00851
00852 }
00853
00854 local int extend_or_end_scatter3(sdyn * b) {
00855
00856 b->to_com();
00857 sdyn *b1, *b2, *b3;
00858 int i=0;
00859 for_all_leaves(sdyn, b, bi) {
00860 if(i==0) b1 = bi;
00861 else if(i==1) b2 = bi;
00862 else if(i==2) b3 = bi;
00863 i++;
00864 }
00865
00866 real r12 = abs(b1->get_pos() - b2->get_pos());
00867 real r23 = abs(b2->get_pos() - b3->get_pos());
00868 real r31 = abs(b3->get_pos() - b1->get_pos());
00869
00870 real m1 = b1->get_mass();
00871 real m2 = b2->get_mass();
00872 real m3 = b3->get_mass();
00873
00874 real k1 = 0.5 * m1 * b1->get_vel() * b1->get_vel();
00875 real k2 = 0.5 * m2 * b2->get_vel() * b2->get_vel();
00876 real k3 = 0.5 * m3 * b3->get_vel() * b3->get_vel();
00877
00878 real phi12 = m1 * m2 / r12;
00879 real phi23 = m2 * m3 / r23;
00880 real phi31 = m3 * m1 / r31;
00881
00882 real mu12 = m1 * m2 / (m1 + m2);
00883 real mu23 = m2 * m3 / (m2 + m3);
00884 real mu31 = m3 * m1 / (m3 + m1);
00885
00886 vector dv = b2->get_vel() - b1->get_vel();
00887 real k12 = 0.5 * mu12 * dv * dv;
00888 real vr12 = dv * (b2->get_pos() - b1->get_pos());
00889
00890 dv = b3->get_vel() - b2->get_vel();
00891 real k23 = 0.5 * mu23 * dv * dv;
00892 real vr23 = dv * (b3->get_pos() - b2->get_pos());
00893
00894 dv = b1->get_vel() - b3->get_vel();
00895 real k31 = 0.5 * mu31 * dv * dv;
00896 real vr31 = dv * (b1->get_pos() - b3->get_pos());
00897
00898
00899
00900 real ttf = TIDAL_TOL_FACTOR;
00901 if (k1 + k2 + k3 >= phi12 + phi23 + phi31
00902 && r12 > LARGE_SEPARATION
00903 && r23 > LARGE_SEPARATION
00904 && r31 > LARGE_SEPARATION
00905 && k12 > phi12 && k23 > phi23 && k31 > phi31
00906 && vr12 > 0 && vr23 > 0 && vr31 > 0
00907 && triple_escape(k12 - phi12, min(r23, r31), m1 + m2, m3, ttf)
00908 && triple_escape(k23 - phi23, min(r31, r12), m2 + m3, m1, ttf)
00909 && triple_escape(k31 - phi31, min(r12, r23), m3 + m1, m2, ttf)) {
00910
00911 return 1;
00912 }
00913
00914
00915
00916
00917
00918
00919
00920 if (r12 * LARGE_SEPARATION_FACTOR < (r23 + r31))
00921 return escape(b3, b1, b2, (k12 - phi12)/mu12, ttf);
00922
00923 if (r23 * LARGE_SEPARATION_FACTOR < (r31 + r12))
00924 return escape(b1, b2, b3, (k23 - phi23)/mu23, ttf);
00925
00926 if (r31 * LARGE_SEPARATION_FACTOR < (r12 + r23))
00927 return escape(b2, b3, b1, (k31 - phi31)/mu31, ttf);
00928
00929 return 0;
00930 }
00931
00932 local int extend_or_end_scatter2(sdyn * b) {
00933
00934 sdyn * d1 = b->get_oldest_daughter();
00935 sdyn * d2 = d1->get_younger_sister();
00936
00937
00938
00939 d2->set_younger_sister(NULL);
00940
00941 kepler k;
00942
00943 sdyn * merger = NULL;
00944 sdyn * single = NULL;
00945
00946
00947
00948 if (d1->get_index() > 3) {
00949 merger = d1;
00950 single = d2;
00951 } else {
00952 merger = d2;
00953 single = d1;
00954 }
00955
00956 set_kepler_from_sdyn(k, d1, d2);
00957
00958
00959 real closest_approach = k.get_periastron();
00960 if (k.get_energy() >= 0
00961 && (d1->get_pos() - d2->get_pos())
00962 * (d1->get_vel() - d2->get_vel()) > 0)
00963 closest_approach = k.get_separation();
00964 else {
00965 return 2;
00966 }
00967
00968 if (closest_approach < d1->get_radius() + d2->get_radius()) {
00969 PRL(closest_approach);
00970 cerr <<"Merge nodes"<<endl;
00971 merge(d1, d2);
00972 d1 = b->get_oldest_daughter();
00973 d1->set_younger_sister(NULL);
00974
00975 #if 0
00976 if (final) {
00977 final->descriptor = triple_merger;
00978 final->escaper = 0;
00979 final->outer_separation = 0;
00980 final->virial_ratio = -1;
00981 }
00982 #endif
00983
00984 } else {
00985
00986 real closest_approach_squared = closest_approach * closest_approach;
00987
00988
00989 merger->set_min_nn_dr2(closest_approach_squared);
00990 merger->set_min_nn_label(single->get_index());
00991
00992 if (closest_approach_squared < single->get_min_nn_dr2()) {
00993
00994
00995
00996 single->set_min_nn_dr2(closest_approach_squared);
00997 single->set_min_nn_label(merger->get_index());
00998 }
00999 }
01000
01001 return 1;
01002 }
01003
01004 int extend_or_end_scatter(sdyn * b, real ttf, bool debug) {
01005
01006 if (b->get_n_steps() > MAX_N_STEPS) {
01007 return 1;
01008 }
01009
01010 int unbound = 0;
01011 if(b->n_leaves()==4) {
01012 unbound = tree_is_unbound(b, ttf, debug);
01013 }
01014 else if(b->n_leaves()==3) {
01015 unbound = extend_or_end_scatter3(b);
01016
01017 } else if(b->n_leaves()==2) {
01018 unbound = extend_or_end_scatter2(b);
01019 } else if(b->n_leaves()==1) {
01020
01021 unbound = 1;
01022 }
01023
01024 return unbound;
01025 }
01026