Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

extend_or_end.C

Go to the documentation of this file.
00001 
00002        //=======================================================//    _\|/_
00003       //  __  _____           ___                    ___       //      /|\
00004      //  /      |      ^     |   \  |         ^     |   \     //          _\|/_
00005     //   \__    |     / \    |___/  |        / \    |___/    //            /|\
00006    //       \   |    /___\   |  \   |       /___\   |   \   // _\|/_
00007   //     ___/   |   /     \  |   \  |____  /     \  |___/  //   /|\     
00008  //                                                       //            _\|/_
00009 //=======================================================//              /|\
00010 
00011 // Code shared by scatter3 and hier3 relating to possible termination
00012 // or analytic extension of motion, or merging two or all stars.
00013 //
00014 // Globally visible functions:
00015 //
00016 //      merge_collisions
00017 //      extend_or_end_scatter
00018 
00019 #include "scatter3.h"
00020 
00021 #define UNPERTURBED_DIAG false
00022 
00023 local void extend_orbits(sdyn3 * b1, sdyn3 * b2, sdyn3 * b3, real& apo)
00024 
00025 // Analytically extend the orbits of the [[1,2],3] hierarchical system.
00026 
00027 {
00028     if ( (b1->get_time() != b2->get_time())
00029          || (b1->get_time() != b3->get_time()) )
00030         err_exit("extend_orbits: inconsistent times");
00031     
00032     real time = b3->get_time();
00033     
00034     kepler inner, outer;
00035 
00036     set_kepler_from_sdyn3(inner, b1, b2);
00037     
00038     real m1 = b1->get_mass();
00039     real m2 = b2->get_mass();
00040     real m3 = b3->get_mass();
00041     real m12 = m1 + m2;
00042     real m123 = m12 + m3;
00043     
00044     outer.set_time(time);
00045     outer.set_total_mass(m123);
00046     
00047     // Center of mass position and velocity of the inner binary:
00048     
00049     vector cmr = (m1 * b1->get_pos() + m2 * b2->get_pos()) / m12;
00050     vector cmv = (m1 * b1->get_vel() + m2 * b2->get_vel()) / m12;
00051     
00052     outer.set_rel_pos(b3->get_pos() - cmr);
00053     outer.set_rel_vel(b3->get_vel() - cmv);
00054 
00055     outer.initialize_from_pos_and_vel();
00056 
00057     // Determine the outer apocenter, to check the stopping criterion
00058     // in the calling routine.
00059 
00060     apo = outer.get_semi_major_axis() * (1 + outer.get_eccentricity());
00061     
00062     if (UNPERTURBED_DIAG) {
00063 
00064         cerr << "  inner binary:  r = " << inner.get_separation()
00065              << "  a = " << inner.get_semi_major_axis()
00066              << "  e = " << inner.get_eccentricity()
00067              << endl
00068              << "  mass = " << inner.get_total_mass() << endl
00069              << "  pos = " << inner.get_rel_pos() << endl
00070              << "  vel = " << inner.get_rel_vel() << endl;
00071         cerr << "  outer binary:  R = " << outer.get_separation()
00072              << "  a = " << outer.get_semi_major_axis() << endl
00073              << "  e = " << outer.get_eccentricity()
00074              << endl
00075              << "  mass = " << outer.get_total_mass() << endl
00076              << "  pos = " << outer.get_rel_pos() << endl
00077              << "  vel = " << outer.get_rel_vel() << endl;
00078 
00079     }
00080 
00081     // Map forward in time by an integral number of inner binary periods
00082     // to an incoming configuration as close as possible to the outgoing one.
00083 
00084     real orbits = 2 * (outer.pred_advance_to_apastron() - time)
00085                                 / inner.get_period();
00086 
00087     // Note: orbits may be too big to fit in an int...
00088 
00089     real time_0 = time;
00090 
00091     real big = 1.e9;
00092     while (orbits > big) {
00093         time += big*inner.get_period();
00094         orbits -= big;
00095     }
00096 
00097     int inner_orbits = (int) (orbits + 0.5);
00098     time += inner_orbits * inner.get_period();
00099 
00100     outer.transform_to_time(time);
00101     
00102     // Note that no modification is needed to the inner orbit
00103     // except to increase its time.
00104     
00105     inner.set_time(time);
00106     
00107     if (UNPERTURBED_DIAG) {
00108 
00109         cerr << "  outer binary:  R = " << outer.get_separation()
00110              << "  a = " << outer.get_semi_major_axis() << endl
00111              << "  e = " << outer.get_eccentricity()
00112              << endl
00113              << "  mass = " << outer.get_total_mass() << endl
00114              << "  pos = " << outer.get_rel_pos() << endl
00115              << "  vel = " << outer.get_rel_vel() << endl;
00116 
00117     }
00118 
00119     // Reconstruct the new sdyn3s:
00120     
00121     b1->get_parent()->set_time(time);
00122     b1->set_time(time);
00123     b2->set_time(time);
00124     b3->set_time(time);
00125 
00126     kepler_pair_to_triple(inner, outer, b1, b2, b3);
00127     
00128 //    cerr << "extend_orbits:  " << inner_orbits << " inner orbits" << endl;
00129 //    cerr << "outer orbit: " << endl;
00130 //    outer.print_elements(cerr);
00131 //    cerr << "inner orbit: " << endl;
00132 //    inner.print_elements(cerr);
00133     
00134 }
00135 
00136 local void stop_integration(sdyn3 * bi, sdyn3 * bj, sdyn3 * bk,
00137                             real ejk, real mjk,
00138                             real sep, real virial_ratio,
00139                             final_state3 * final = NULL)
00140 {
00141     if (!final) return;
00142 
00143     real ajk = 0.5 * mjk / abs(ejk);
00144 
00145     final->descriptor = stopped;
00146     final->sma = ajk;
00147 
00148     real ang_mom = abs((bk->get_pos() - bj->get_pos())
00149                        ^ (bk->get_vel() - bj->get_vel()));
00150 
00151     real ecc2 = 1 - ang_mom * ang_mom / (mjk * ajk);
00152     
00153     if (ecc2 < 1.e-10) {
00154 
00155         // Take care with small eccentricities! 
00156 
00157         kepler k;
00158         set_kepler_from_sdyn3(k, bj, bk);
00159         final->ecc = k.get_eccentricity();
00160 
00161     } else
00162         final->ecc = sqrt(ecc2);
00163 
00164     final->escaper = bi->get_index();
00165     final->virial_ratio = virial_ratio;
00166     final->outer_separation = sep;
00167 }
00168 
00169 local int escape(sdyn3 * bi, sdyn3 * bj, sdyn3 * bk,
00170                  real ejk,                              //(for convenience)
00171                  initial_state3& init,
00172                  intermediate_state3 * inter = NULL,
00173                  final_state3 * final = NULL)
00174 
00175 // Return true iff bi is escaping from the center of mass of bj and bk.
00176 // Perform analytic continuation if appropriate.
00177 // On entry, we already know that i is "widely" separated from j and k.
00178 
00179 {
00180     if (final) final->descriptor = unknown_final;
00181 
00182     if (ejk >= 0) return 0;             // Inner pair not bound.
00183 
00184     real mi = bi->get_mass();
00185     real mj = bj->get_mass();
00186     real mk = bk->get_mass();
00187     real mjk = mj + mk;
00188 
00189     // Center of mass position and velocity of j-k "binary":
00190 
00191     vector cmr = (mj * bj->get_pos() + mk * bk->get_pos()) / mjk;
00192     vector cmv = (mj * bj->get_vel() + mk * bk->get_vel()) / mjk;
00193 
00194     // Return immediately if the third particle is approaching the binary,
00195     // unless r_stop < 0 (meaning that the integration is to be terminated
00196     // if we pass apastron).  Note that NO analytic extension is performed
00197     // on the initial incoming orbit -- it is assumed that the initial
00198     // conditions take care of this.
00199 
00200     vector dv = bi->get_vel() - cmv;
00201     vector dr = bi->get_pos() - cmr;
00202 
00203     // PRL(abs(dr));
00204     // PRL(abs(dv));
00205     // PRL(dr*dv);
00206     // PRL(init.r_stop);
00207 
00208     if (dr*dv <= 0 && init.r_stop > 0) return 0;
00209 
00210     real sep = abs(dr);
00211     real virial_ratio = .5 * dv * dv * sep / (mi + mj + mk);
00212 
00213     // Test stopping criterion.
00214 
00215     // PRL(sep);
00216 
00217     if (sep > abs(init.r_stop)
00218         || (inter && init.r_stop < 0 && dr*dv <= 0 && inter->n_osc > 0)) {
00219 
00220 //      cerr << "stopping... \n";
00221 //      cerr << "  sep = " << sep << "  r_stop = " << init.r_stop
00222 //           << "  dr*dv = " << dr*dv;
00223 //      if (inter) cerr << "  n_osc = " << inter->n_osc;
00224 //      cerr << endl;
00225 
00226         stop_integration(bi, bj, bk, ejk, mjk,
00227                          sep, virial_ratio, final);
00228         return 1;
00229     }
00230 
00231     // Test for sufficiently unperturbed inner binary.
00232     
00233     real ajk = 0.5 * mjk / abs(ejk);
00234 
00235     // PRL(ajk);
00236 
00237     // Determine limiting radius for "negligible" tidal perturbation
00238     // Note that the term in the denominator is mjk + mi, not just
00239     // mi, in order to prevent problems with low-mass third stars.
00240 
00241     // The use of r_stop is a kludge to allow "flyby" experiments where
00242     // we catch the outcoming particle at some specific radius.  For the
00243     // strictest flyby experiments (see flyby3.C), r_stop < 0, meaning
00244     // we stop at |r_stop| or apocenter.  In this case ONLY, let r_stop
00245     // override the tidal limit.  If r_stop > 0, assume that the built-in
00246     // tidal parameters are OK.
00247 
00248     real rlimit = (ajk + bi->get_radius())
00249                       * pow(init.tidal_tol_factor * mjk / (mi + mjk), -1/3.0);
00250     if (init.r_stop < 0) rlimit = max(rlimit, abs(init.r_stop));
00251 
00252     // PRL(rlimit);
00253 
00254     if (sep < rlimit) return 0;
00255 
00256     // Test for sufficiently non-perturbed outer binary. The safety
00257     // factor is reduced at large radii.
00258 
00259     real scaled_safety_factor = ENERGY_SAFETY_FACTOR * rlimit / sep;
00260 
00261 //    int p = cerr.precision(STD_PRECISION);
00262 //    cerr << "inner unperturbed, sep, rlim, factor, |v - 1| = " << endl;
00263 //    cerr << "   " << sep <<" "<< rlimit <<" "<< scaled_safety_factor
00264 //       <<" "<< abs(virial_ratio - 1) << endl;
00265 //    cerr.precision(p);
00266 
00267     // PRL(virial_ratio);
00268 
00269     if (abs(virial_ratio - 1) < scaled_safety_factor) return 0;
00270 
00271     // Now outer binary is either clearly bound or clearly unbound.
00272 
00273     if (virial_ratio > 1) {
00274 
00275         // Body bi is escaping.
00276 
00277         if (final) {
00278 
00279             if (bi->get_index() == 1)   // Initial binary was (1,2).
00280                 final->descriptor = exchange_1;
00281             else if (bi->get_index() == 2)
00282                 final->descriptor = exchange_2;
00283             else if (bi->get_index() == 3)
00284                 final->descriptor = preservation;
00285             else
00286                 final->descriptor = unknown_final;
00287 
00288             final->sma = ajk;
00289             real ang_mom = abs((bk->get_pos() - bj->get_pos())
00290                                ^ (bk->get_vel() - bj->get_vel()));
00291 
00292             real ecc2 = 1 - ang_mom * ang_mom / (mjk * ajk);
00293             if (ecc2 < 1.e-10) {
00294 
00295                 // Take care with small eccentricities! 
00296 
00297                 kepler k;
00298                 set_kepler_from_sdyn3(k, bj, bk);
00299                 final->ecc = k.get_eccentricity();
00300 
00301             } else
00302                 final->ecc = sqrt(ecc2);
00303 
00304             final->escaper = bi->get_index();
00305             final->virial_ratio = virial_ratio;
00306             final->outer_separation = sep;
00307         }
00308 
00309         return 1;
00310 
00311     } else {
00312 
00313         // Analytically extend the orbits by an integral number
00314         // of binary periods.
00315 
00316         real e = energy(bi->get_parent());
00317 
00318         if (UNPERTURBED_DIAG) 
00319             cerr << "Beginning analytic extension at time "
00320                  << bi->get_parent()->get_time()
00321                            + bi->get_parent()->get_time_offset()
00322                  << endl;
00323 
00324         real apo;
00325         extend_orbits(bj, bk, bi, apo);
00326 
00327         if (inter) inter->n_kepler++;
00328 
00329         if (UNPERTURBED_DIAG)
00330             cerr << "Done.  Energy error = "
00331                  << energy(bi->get_parent()) - e
00332                  << endl;
00333 
00334         // See if we exceeded the stopping condition during the extension.
00335 
00336         if (apo >= init.r_stop) {
00337             stop_integration(bi, bj, bk, ejk, mjk,
00338                              min(apo, abs(init.r_stop)), virial_ratio, final);
00339             return 1;
00340         }
00341     }
00342     
00343     return 0;
00344 }
00345 
00346 // set_merger_mass_and_radius: determine mass and radius of merger product
00347 
00348 local void set_merger_mass_and_radius(sdyn3 * bn, sdyn3 * bi, sdyn3 * bj)
00349 {
00350     bn->set_mass(bi->get_mass() + bj->get_mass());       // No mass loss
00351     bn->set_radius(bi->get_radius() + bj->get_radius()); // R \propto M
00352 }
00353 
00354 // set_merger_dyn: determine pos, vel, acc and jerk of merger product,
00355 //                 and determine energy dissipation
00356 
00357 local void set_merger_dyn(sdyn3 * bn, sdyn3 * bi, sdyn3 * bj)
00358 {
00359     real  mi = bi->get_mass();
00360     real  mj = bj->get_mass();
00361     real  m_inv = 1/(mi + mj);
00362     
00363     bn->set_pos((mi*bi->get_pos() + mj*bj->get_pos())*m_inv);
00364     bn->set_vel((mi*bi->get_vel() + mj*bj->get_vel())*m_inv);
00365     bn->set_acc((mi*bi->get_acc() + mj*bj->get_acc())*m_inv);
00366     bn->set_jerk((mi*bi->get_jerk() + mj*bj->get_jerk())*m_inv);
00367 
00368     vector d_pos = bi->get_pos() - bj->get_pos();
00369     real rij = sqrt(d_pos*d_pos);
00370 
00371     vector d_vel = bi->get_vel() - bj->get_vel();
00372     real vij2 = d_vel*d_vel;
00373 
00374     real eij_pot = -mi * mj / rij;
00375     real eij_kin = 0.5 * mi * mj * m_inv * vij2;
00376 
00377     // Include tidal term from spectator star, if any:
00378 
00379     sdyn3 * b = bi->get_parent();
00380     sdyn3 * bk = NULL;
00381 
00382     for_all_daughters(sdyn3, b, bb)
00383         if (bb != bi && bb != bj) bk = bb;
00384 
00385     real tidal_pot = 0;
00386     if (bk) {
00387         real mn = mi + mj;
00388         real mk = bk->get_mass();
00389         tidal_pot = -mn * mk / abs(bn->get_pos() - bk->get_pos())
00390                     + mi * mk / abs(bi->get_pos() - bk->get_pos())
00391                     + mj * mk / abs(bj->get_pos() - bk->get_pos());
00392     }
00393 
00394     bn->set_energy_dissipation(bi->get_energy_dissipation()
00395                                + bj->get_energy_dissipation()
00396                                + eij_pot + eij_kin
00397                                - tidal_pot);
00398 
00399 }
00400 
00401 // merge: replace two particles by their center of mass.
00402 
00403 local void merge(sdyn3 * bi, sdyn3 * bj)
00404 {
00405     sdyn3 * b = bi->get_parent();
00406     if (b != bj->get_parent()) err_exit("merge: parent conflict...");
00407 
00408     // Note: any stories attached to the particles are lost.
00409 
00410     sdyn3 * bn = new sdyn3();
00411 
00412 //    int p = cerr.precision(STD_PRECISION);
00413 //    cerr << "entering merge(" << bi->get_index() << ", " << bj->get_index()
00414 //         << ") with r1 = " << bi->get_pos() << "\n                     "
00415 //         << " and r2 = " << bj->get_pos()   << endl
00416 //         << "         at t = " << b->get_time() << endl;
00417 //    cerr.precision(p);
00418 
00419     set_merger_mass_and_radius(bn, bi, bj);
00420     set_merger_dyn(bn, bi, bj);
00421     bn->set_time(bi->get_time());
00422 
00423     // Construct the new index as one more than the maximum existing index.
00424 
00425 //    int max_index = 0;
00426 //    for_all_daughters(sdyn3, b, bb)
00427 //      if (max_index < bb->get_index())
00428 //          max_index = bb->get_index();
00429 //
00430 //    bn->set_label(max_index+1);
00431 
00432     // Construct the new index by adding the component indices,
00433     // then adding 1 if neither component is a merger product
00434     // (so 1 + 2 --> 4, 1 + 3 --> 5, 2 + 3 --> 6, 1 + 2 + 3 --> 7.
00435 
00436     int new_index = bi->get_index() + bj->get_index();
00437     if (bi->get_index() < 4 && bj->get_index() < 4) new_index++;
00438     bn->set_label(new_index);
00439 
00440     detach_node_from_general_tree(*bi);
00441     detach_node_from_general_tree(*bj);
00442   
00443     add_node(*bn, *b);
00444 }
00445 
00446 // merge_collisions: recursively merge any stars in contact.
00447 
00448 void merge_collisions(sdyn3 * b)
00449 {
00450     int coll = 1;
00451     while (coll) {
00452 
00453         coll = 0;
00454         for_all_daughters(sdyn3, b, bi)
00455             {
00456             if (coll) break;
00457             for (sdyn3 * bj = bi->get_younger_sister(); bj != NULL; 
00458                  bj = bj->get_younger_sister()) {
00459 
00460                 if ( abs(bi->get_pos() - bj->get_pos())
00461                       < (bi->get_radius() + bj->get_radius()) ) {
00462 
00463                     merge(bi, bj);
00464                     coll = 1;
00465                     break;
00466                 }
00467             }
00468         }
00469     }
00470 }
00471 
00472 // triple_escape: return 1 if star 3 is unbound with respect to the center
00473 //                of mass of stars 1 and 2 (distance r3) and is a negligible
00474 //                perturber of the (1,2) hyperbolic orbit.
00475 
00476 local int triple_escape(real e12, real r3, real m12, real m3,
00477                         real tidal_tol_factor)
00478 {
00479     if (e12 < 0) return 0; // e12 = energy per unit reduced mass of pair (1,2)
00480 
00481     real a12 = 0.5 * m12 / e12;
00482 
00483     //----------------------------------------------------------------------
00484     // Hmmm... Still a problem with pow on RH 5.2?
00485 
00486     // if (r3 > a12 * pow(tidal_tol_factor * m12 / (m3 + m12), -1/3.0))
00487 
00488     // The m12 in the denominator here includes the tidal effect of (1,2) on 3.
00489 
00490     real tid_fac = tidal_tol_factor * m12 / (m3 + m12);
00491     real ratio = a12/r3;
00492 
00493     if (ratio*ratio*ratio > tid_fac)
00494     //----------------------------------------------------------------------
00495         return 1;
00496     else
00497         return 0;
00498 }
00499 
00500 local int extend_or_end_scatter3(sdyn3 * b,
00501                                  initial_state3& init,
00502                                  intermediate_state3 * inter = NULL,
00503                                  final_state3 * final = NULL)
00504 {
00505     b->to_com();          // map the whole system to center-of-mass frame
00506 
00507     sdyn3 * b1 = b->get_oldest_daughter();
00508     sdyn3 * b2 = b1->get_younger_sister();
00509     sdyn3 * b3 = b2->get_younger_sister();
00510 
00511     real r12 = abs(b1->get_pos() - b2->get_pos());
00512     real r23 = abs(b2->get_pos() - b3->get_pos());
00513     real r31 = abs(b3->get_pos() - b1->get_pos());
00514 
00515     real m1 = b1->get_mass();
00516     real m2 = b2->get_mass();
00517     real m3 = b3->get_mass();
00518 
00519     real k1 = 0.5 * m1 * b1->get_vel() * b1->get_vel();
00520     real k2 = 0.5 * m2 * b2->get_vel() * b2->get_vel();
00521     real k3 = 0.5 * m3 * b3->get_vel() * b3->get_vel();
00522 
00523     real phi12 = m1 * m2 / r12;
00524     real phi23 = m2 * m3 / r23;
00525     real phi31 = m3 * m1 / r31;
00526 
00527     real mu12 = m1 * m2 / (m1 + m2);
00528     real mu23 = m2 * m3 / (m2 + m3);
00529     real mu31 = m3 * m1 / (m3 + m1);
00530 
00531     vector dv = b2->get_vel() - b1->get_vel();
00532     real k12 = 0.5 * mu12 * dv * dv;
00533     real vr12 = dv * (b2->get_pos() - b1->get_pos());
00534 
00535     dv = b3->get_vel() - b2->get_vel();
00536     real k23 = 0.5 * mu23 * dv * dv;
00537     real vr23 = dv * (b3->get_pos() - b2->get_pos());
00538 
00539     dv = b1->get_vel() - b3->get_vel();
00540     real k31 = 0.5 * mu31 * dv * dv;
00541     real vr31 = dv * (b1->get_pos() - b3->get_pos());
00542 
00543     // First test for ionization.
00544 
00545     if (k1 + k2 + k3 >= phi12 + phi23 + phi31
00546         && r12 > LARGE_SEPARATION 
00547         && r23 > LARGE_SEPARATION
00548         && r31 > LARGE_SEPARATION
00549         && k12 > phi12 && k23 > phi23 && k31 > phi31
00550         && vr12 > 0 && vr23 > 0 && vr31 > 0
00551         && triple_escape(k12 - phi12, min(r23, r31), m1 + m2, m3,
00552                          init.tidal_tol_factor)
00553         && triple_escape(k23 - phi23, min(r31, r12), m2 + m3, m1,
00554                          init.tidal_tol_factor)
00555         && triple_escape(k31 - phi31, min(r12, r23), m3 + m1, m2,
00556                          init.tidal_tol_factor)) {
00557 
00558         if (final) {
00559             final->descriptor = ionization;
00560             final->virial_ratio = min(min(k12/phi12, k23/phi23), k31/phi31);
00561             final->outer_separation = -1;
00562             final->escaper = -1;                // -1 means all escaping
00563         }
00564 
00565         return 1;
00566     }
00567 
00568     // Now test the closest pair and the third star for escape.
00569     // Function "escape" also does analytic extension, if appropriate.
00570     // Note that the emergency stopping criterion R > |r_stop| returns
00571     // looking like an escape has occurred. This should be decoupled from
00572     // the escape test (someday).
00573 
00574     if (r12 * LARGE_SEPARATION_FACTOR < (r23 + r31))
00575         return escape(b3, b1, b2, (k12 - phi12)/mu12, init, inter, final);
00576 
00577     if (r23 * LARGE_SEPARATION_FACTOR < (r31 + r12))
00578         return escape(b1, b2, b3, (k23 - phi23)/mu23, init, inter, final);
00579 
00580     if (r31 * LARGE_SEPARATION_FACTOR < (r12 + r23))
00581         return escape(b2, b3, b1, (k31 - phi31)/mu31, init, inter, final);
00582 
00583     return 0;
00584 }
00585 
00586 local int extend_or_end_scatter2(sdyn3 * b, final_state3 * final = NULL)
00587 {
00588     sdyn3 * d1 = b->get_oldest_daughter();
00589     sdyn3 * d2 = d1->get_younger_sister();
00590 
00591     // Consistency (just in case):
00592 
00593     d2->set_younger_sister(NULL);
00594 
00595     kepler k;
00596 
00597     sdyn3 * merger = NULL;
00598     sdyn3 * single = NULL;
00599 
00600     // One of the two stars must be a merger product.
00601 
00602     if (d1->get_index() > 3) {
00603         merger = d1;
00604         single = d2;
00605     } else {
00606         merger = d2;
00607         single = d1;
00608     }
00609 
00610     set_kepler_from_sdyn3(k, d1, d2);
00611 
00612     real closest_approach = k.get_periastron();
00613     if (k.get_energy() >= 0
00614         && (d1->get_pos() - d2->get_pos())
00615             * (d1->get_vel() - d2->get_vel()) > 0)
00616         closest_approach = k.get_separation();
00617 
00618     if (closest_approach < d1->get_radius() + d2->get_radius()) {
00619 
00620         merge(d1, d2);
00621         d1 = b->get_oldest_daughter();
00622         d1->set_younger_sister(NULL);   // Again, just in case.
00623 
00624         if (final) {
00625             final->descriptor = triple_merger;
00626             final->escaper = 0;                // 0 means no escaper
00627             final->outer_separation = 0;
00628             final->virial_ratio = -1;
00629         }
00630 
00631     } else {
00632 
00633         real closest_approach_squared = closest_approach * closest_approach;
00634 
00635         merger->set_min_nn_dr2(closest_approach_squared);
00636         merger->set_min_nn_label(single->get_index());
00637 
00638         if (closest_approach_squared < single->get_min_nn_dr2()) {
00639             single->set_min_nn_dr2(closest_approach_squared);
00640             single->set_min_nn_label(merger->get_index());
00641         }
00642 
00643 
00644         if (final) {
00645 
00646             if (k.get_energy() < 0) {
00647 
00648                 if (single->get_index() == 1)
00649                     final->descriptor = merger_binary_1;
00650                 else if (single->get_index() == 2)
00651                     final->descriptor = merger_binary_2;
00652                 else if (single->get_index() == 3)
00653                     final->descriptor = merger_binary_3;
00654                 else
00655                     final->descriptor = unknown_final;
00656 
00657                 final->sma = k.get_semi_major_axis();
00658                 final->ecc = k.get_eccentricity();
00659                 final->outer_separation = -1;
00660                 final->escaper = 0;
00661                 final->virial_ratio = -1;
00662 
00663             } else {
00664 
00665                 if (single->get_index() == 1)
00666                     final->descriptor = merger_escape_1;
00667                 else if (single->get_index() == 2)
00668                     final->descriptor = merger_escape_2;
00669                 else if (single->get_index() == 3)
00670                     final->descriptor = merger_escape_3;
00671                 else
00672                     final->descriptor = unknown_final;
00673 
00674                 final->outer_separation = k.get_separation();
00675                 final->escaper = single->get_index();
00676                 final->virial_ratio = k.get_energy() * k.get_separation() 
00677                                                      / k.get_total_mass() - 1;
00678             }
00679         }
00680     }
00681 
00682     return 1;
00683 }
00684 
00685 local int extend_or_end_scatter1(final_state3 * final = NULL)
00686 {
00687     if (final) {
00688         final->descriptor = triple_merger;
00689         final->escaper = 0;                      // 0 denotes no escaper
00690         final->outer_separation = 0;
00691         final->virial_ratio = -1;
00692     }
00693 
00694     return 1;
00695 }
00696 
00697 // extend_or_end_scatter:
00698 //      set the final state and return 1 iff the scattering is over
00699 //      analytically extend the motion if appropriate
00700 
00701 int extend_or_end_scatter(sdyn3 * b,
00702                           initial_state3& init,
00703                           intermediate_state3 * inter,  // default = NULL
00704                           final_state3 * final)         // default = NULL
00705 {
00706     // Place an absolute limit on the total number of steps:
00707 
00708     if (init.r_stop == VERY_LARGE_NUMBER && b->get_n_steps() > MAX_N_STEPS) {
00709         if (final) final->descriptor = stopped;
00710         return 1;
00711     }
00712 
00713     int n = 0;
00714     for_all_daughters(sdyn3, b, bb) n++;
00715 
00716     // Set some default values for these quantities:
00717 
00718     if (final) {
00719         final->sma = -1;
00720         final->ecc = -1;
00721     }
00722 
00723     if (n == 3) 
00724         return extend_or_end_scatter3(b, init, inter, final);
00725     else if (n == 2)
00726         return extend_or_end_scatter2(b, final);
00727     else if (n == 1)
00728         return extend_or_end_scatter1(final);
00729     else {
00730         cerr << "extend_or_end_scatter: n = " << n << endl;
00731         exit(1);
00732     }
00733     return 0; // To keep HP g++ happy!
00734 }

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