Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

hdyn_tree.C

Go to the documentation of this file.
00001 
00002        //=======================================================//    _\|/_
00003       //  __  _____           ___                    ___       //      /|\ ~
00004      //  /      |      ^     |   \  |         ^     |   \     //          _\|/_
00005     //   \__    |     / \    |___/  |        / \    |___/    //            /|\ ~
00006    //       \   |    /___\   |  \   |       /___\   |   \   // _\|/_
00007   //     ___/   |   /     \  |   \  |____  /     \  |___/  //   /|\ ~
00008  //                                                       //            _\|/_
00009 //=======================================================//              /|\ ~
00010 
00011 //
00012 //  hdyn_tree.C: functions related to tree evolution in kira.
00013 //.............................................................................
00014 //    version 1:  Nov 1995   Jun Makino, Steve McMillan
00015 //.............................................................................
00016 //
00017 //  Externally visible functions:
00018 //
00019 //      real   hdyn::distance_to_sister_squared
00020 //      hdyn*  hdyn::new_sister_node
00021 //      int    hdyn::adjust_tree_structure
00022 //
00023 //      void   split_top_level_node
00024 //      void   combine_top_level_nodes
00025 //
00026 //  The functions that actually make changes to the tree structure are
00027 //
00028 //      void split_top_level_node
00029 //      void combine_top_level_nodes
00030 //      void combine_low_level_nodes    (local)
00031 //
00032 //.............................................................................
00033 //
00034 //  NOTE (SLWM, 7/97): when a binary node is created, update_binary_sister
00035 //  is not called, so the components' timesteps, etc. may not be up to date
00036 //  until the next time step is taken.  This is not generally a problem,
00037 //  but may cause difficulties in set_unperturbed_timestep if a lower-level
00038 //  node takes a step before the higher-level binary is advanced.
00039 //
00040 //.............................................................................
00041 
00042 #include "hdyn.h"
00043 #include <star/dstar_to_kira.h>
00044 #include <star/single_star.h>
00045 
00046 // Note:  The *only* places in kira where "close" is defined, for
00047 //        purposes of making binary trees, are too_close() and
00048 //        new_sister_node().
00049 //
00050 // Close_criterion is now a variable, part of kira_options:
00051 //
00052 //              0: "close" criterion based on distance
00053 //              1:                            potential
00054 //              2:                            force
00055 
00056 // Both criteria 1 and 2 expand the binary distance criterion as masses
00057 // increase.  Both appear to work (Steve, 7/29/98).
00058 
00059 real hdyn::distance_to_sister_squared()
00060 {
00061     vector d_sep = pos - get_binary_sister()->get_pos();
00062     return d_sep * d_sep;
00063 }
00064 
00065 local void init_predictor_tree(hdyn * b)
00066 {
00067     if (! b->is_root()) {
00068         b->init_pred();
00069         b->store_old_force();
00070     }
00071     for_all_daughters(hdyn,b,bb) init_predictor_tree(bb);
00072 }
00073 
00074 // synchronize_branch:  Synchronize parent and sister nodes up to, but
00075 //                      not including, the specified ancestor.
00076 
00077 local void synchronize_branch(hdyn * bi, hdyn * ancestor)
00078 {
00079     if (!is_descendent_of(bi, ancestor, 0))
00080         err_exit("synchronize_branch: bi not descended from ancestor");
00081 
00082     for (hdyn * bb = bi; bb != ancestor; bb = bb->get_parent()) {
00083 
00084         // Synchronize sister node:
00085 
00086         bb->get_binary_sister()->synchronize_node();
00087 
00088         // Synchronize parent:
00089 
00090         bb->get_parent()->synchronize_node();
00091     }
00092 }
00093 
00094 local inline real max_mass(hdyn* b)
00095 {
00096     real m_max = 0;
00097     if (b->is_parent()) {
00098         for_all_daughters(hdyn, b, bb)
00099             if (bb->get_mass() > m_max)
00100                 m_max = max(m_max, max_mass(bb));
00101     } else
00102         m_max = b->get_mass();
00103 
00104     return m_max;
00105 }
00106 
00107 local inline real n_mass(hdyn* b)
00108 {
00109     // Choose which mass we use in the binary criterion.
00110 
00111     // Must be careful to avoid "polymerization" of clumps containing
00112     // very massive stars.  Try limiting the mass of a node to the
00113     // maximum mass of any of its leaves...
00114 
00115     // return b->get_mass();
00116 
00117     return max_mass(b);
00118 }
00119 
00120 local bool number_of_daughter_nodes_exceeds(node * b, int n)
00121 {
00122     int nn = 0;
00123 
00124     for_all_daughters(node, b, bb)
00125         if (++nn > n)
00126             return true;
00127 
00128     return false;
00129 }
00130 
00131 local void halve_timestep(hdyn * b)
00132 {
00133     b->set_timestep(0.5 * b->get_timestep());
00134 }
00135 
00136 local void print_relative_energy_and_period(hdyn* bi, hdyn* bj)
00137 {
00138     real E, P;
00139     get_total_energy_and_period(bi, bj, E, P);
00140 
00141     cerr << "relative E/mu = " << E << flush;
00142 
00143     if (E < 0)
00144         cerr << "  P = " << P;                          // no endl, note
00145 }
00146 
00147 
00148 local bool too_close(hdyn * bi, hdyn * bj, real limit_sq,
00149                      bool print = true)
00150 {
00151     if (bi == bj)
00152         return false;
00153 
00154     real gap_sq = square(bi->get_pos() - bj->get_pos());
00155 
00156     // Binary criterion modified 7/98 by SLWM and SPZ to depend on
00157     // acceleration; modified again by SLWM and JM to include potential.
00158     // The criteria below are chosen to reduce to the simple distance
00159     // expressions when all masses are equal.
00160 
00161     bool close;
00162     real mass_factor = 1;               // default (DISTANCE criterion:
00163                                         //              rij  <  d_min)
00164 
00165     if (bi->get_kira_options()->close_criterion > 0) {
00166 
00167         mass_factor = 0.5 * (n_mass(bi) + n_mass(bj)) / bi->get_mbar();
00168 
00169         if (bi->get_kira_options()->close_criterion == 1) {
00170 
00171             // POTENTIAL criterion:  (mi + mj) / rij  >  2 <m> / d_min
00172             //
00173             //          ==>  rij  <  0.5 * (mi+mj) * d_min / <m>
00174 
00175             mass_factor *= mass_factor;
00176 
00177         } else if (bi->get_kira_options()->close_criterion == 2) {
00178 
00179             // FORCE criterion:  (mi + mj) / rij^2  >  2 <m> / d_min^2
00180             //
00181             //          ==>  rij^2  <  0.5 * (mi + mj) * d_min^2 / <m>
00182 
00183         }
00184 
00185     }
00186 
00187     close = (gap_sq < mass_factor * limit_sq);
00188 
00189     if (close && print && bi->get_kira_diag()->tree
00190                        && bi->get_kira_diag()->tree_level > 0) {
00191         cerr << endl << "*** "; bi->print_label(cerr);
00192         cerr << " too close to "; bj->print_label(cerr);
00193         cerr << " (criterion " << bi->get_kira_options()->close_criterion
00194              << ")" << endl;
00195     }
00196 
00197     return close;
00198 }
00199 
00200 local bool too_big(hdyn * bi, real limit_sq)
00201 {
00202     hdyn *od = bi->get_oldest_daughter();
00203     if (od == NULL)
00204         return false;
00205 
00206     // The next if statement prevents an unperturbed binary from being
00207     // split even if it is large.
00208 
00209     if (od->get_kepler()) return false;
00210 
00211     // Expand this to extend binaries with small perturbation which are
00212     // not actually unperturbed.  May need other checks on nn distance,
00213     // timestep, etc...  (Steve, 12/12/01)
00214 
00215     if (od->get_valid_perturbers()) {
00216         real pert2 = od->get_perturbation_squared();
00217         // if (pert2 >= 0 && pert2 <= od->get_gamma2()) return false;
00218         if (pert2 >= 0 && pert2 <= 1.e-10) return false;
00219     }
00220 
00221     bool big = !too_close(od, od->get_younger_sister(), limit_sq, false);
00222 
00223     // Don't allow a slow binary to be split, but schedule the slow
00224     // motion to be stopped at next apocenter.
00225 
00226     if (big && od->get_slow()) {
00227         if (!od->get_slow()->get_stop()) {
00228             cerr << "too_big: scheduling end of slow motion for "
00229                  << bi->format_label() << " at time " << bi->get_system_time()
00230                  << endl;
00231             od->get_slow()->set_stop();
00232         }
00233         return false;
00234     }
00235 
00236     if (big && bi->get_kira_diag()->tree
00237             && bi->get_kira_diag()->tree_level > 0)
00238         cerr << endl << "*** " << bi->format_label() << " too big" << endl;
00239 
00240     return big;
00241 }
00242 
00243 // new_sister_node:  Check to see if a given node is too near any other.
00244 //                   Return a pointer to the node that should become the
00245 //                   new sister, or NULL if the tree is OK as is.
00246 //
00247 //                   **** Used only by adjust_low_level_node.           ****
00248 //                   **** Called twice, with 'this' = either component. ****
00249 
00250 hdyn* hdyn::new_sister_node(bool & top_level_combine)
00251 {
00252     top_level_combine = false;  // if true, combine top level nodes on return;
00253                                 // if false, combine lower level nodes if a
00254                                 //    non-NULL value is returned
00255 
00256     // Note on multiples from Steve, 10/21/98; extended discussion
00257     // from Steve for Steve added 6/6-13/00.  Some care is needed in
00258     // dealing with multiples because of a "feature" of function
00259     // calculate_acc_and_jerk_on_low_level_node (hdyn_ev.C):
00260     //
00261     // If (A, B) is the top-level binary of a multiple, and if A is
00262     // a leaf with nn under B, then both A and B's nn pointers will
00263     // be correctly set (A to the leaf under B, B to A).  However, if
00264     // A is a composite node containing B's nn, then A's nn will be
00265     // B (or a leaf under B), but B's nn will be A (efficiency issue
00266     // in hdyn_ev).  Note that 'this' in this function may be either
00267     // A or B, leading (for a triple) to four distinct possibilities.
00268     // Suppose (a,b) is a binary where b is about to become the sister
00269     // of a perturber c. Then, depending on the ordering of the
00270     // particles and which one is 'this', we can have:
00271     //
00272     //
00273     //       O          A = (a,b), B = c, 'this' = A
00274     //      / \         nn of A is c, nn of c is A
00275     //     A   c        nn of a is b, nn of b is c
00276     //    / \                                                   ~
00277     //   a   b          exchange will not be detected until
00278     //                  component a is advanced (return at *)
00279     //
00280     //
00281     //       O          A = (a,b), B = c, 'this' = c
00282     //      / \         nn of A is c, nn of c is A
00283     //     A   c        nn of a is b, nn of b is c
00284     //    / \                                                   ~
00285     //   a   b          exchange will not be detected until
00286     //                  component a is advanced (return at *)
00287     //
00288     //
00289     //       O          A = c, B = (a,b), 'this' = c
00290     //      / \         nn of c is b, nn of B is c
00291     //     c   B        nn of a is b, nn of b is c
00292     //        / \                                               ~
00293     //       a   b      exchange will be detected when c
00294     //                  is advanced
00295     //
00296     //
00297     //       O          A = c, B = (a,b), 'this' = B
00298     //      / \         nn of c is b, nn of B is c
00299     //     c   B        nn of a is b, nn of b is c
00300     //        / \                                               ~
00301     //       a   b      exchange will be detected when c
00302     //                  is advanced
00303     //
00304     // Thus, a close encounter between (e.g.) triple members will not be
00305     // picked up on integration of the outer binary if A is composite,
00306     // but it will be if A is a leaf.  An exchange in the former case must
00307     // be detected when A's internal motion is integrated (leaves under A
00308     // have the correct nn pointers).  This is OK, as there is currently
00309     // no provision for such changes to be triggered by the parent node.
00310     // However, proper account must then be taken of the fact that B's nn
00311     // may not be a leaf, but A.  Failure to do this can lead to runaway
00312     // time steps (--> 0) when a close encounter goes undetected.
00313     //
00314     // Additional note (Steve, 6/14/00).  Unfortunately, it is possible
00315     // that the internal motion never gets the chance to trigger the
00316     // exchange, as the parent node time step may run away first.
00317     // Specific example:  A is a receding unbound pair and B happens to
00318     // pass close to A's center of mass.  We flag this by checking for
00319     // (a) a strongly perturbed binary with nn lying between its components
00320     // (i.e. the cause), or (b) disparate center of mass and component
00321     // time steps in a strongly perturbed binary (the effect).  (See the
00322     // use of "check_binary_params" below.)  We then synchronize the
00323     // daughter nodes and reduce their time steps in order to guarantee
00324     // that they will be on the integration list next time around, and
00325     // identify the configuration at the component level by including
00326     // an explicit check (**) on the perturbation within this function.
00327 
00328     if (nn->get_parent() == parent)     // already sisters, so no change needed
00329         return NULL;                    // (* - see note above)
00330 
00331     real mass_factor = 1;               // default (DISTANCE criterion)
00332 
00333     if (options->close_criterion > 0) {
00334 
00335         real m = n_mass(this);
00336         mass_factor = (m + n_mass(get_binary_sister())) / (m + n_mass(nn));
00337 
00338         if (options->close_criterion == 1) {
00339 
00340             // POTENTIAL criterion:
00341 
00342             mass_factor *= mass_factor;
00343 
00344         } else if (options->close_criterion == 2) {
00345 
00346             // FORCE criterion:
00347 
00348         }
00349     }
00350 
00351     bool nn_too_close = (distance_to_sister_squared()
00352                                 > d_nn_sq * lag_factor * mass_factor);
00353 
00354     if (!nn_too_close) {        // (** Steve 6/14/00)  Relax the distance
00355                                 // criterion for a strongly perturbed binary,
00356                                 // as described above.  Perhaps better to
00357                                 // check explicitly the position of nn
00358                                 // relative to the parent node?
00359 
00360         nn_too_close = (perturbation_squared > 1
00361                         && distance_to_sister_squared() > d_nn_sq);
00362 
00363         if (nn_too_close && diag->tree && diag->tree_level > 1) {
00364             cerr << "in new_sister_node for " << format_label()
00365                  << " at time " << system_time << ":" << endl;
00366             cerr << "    candidate new sister for strongly perturbed binary is "
00367                  << nn->format_label() << endl;
00368         }
00369 
00370     }
00371 
00372     if (nn_too_close) {
00373         
00374         // Nearest neighbor is closer than binary sister.
00375         //
00376         // Should check whether or not this and nn are mutual nearest
00377         // neighbors.  If they are, then we are done.  If not, then we
00378         // must be a little more careful.  We should further check if
00379         // one of nn's ancestors can become the new sister.
00380         //
00381         //    Criterion:  If the nearest neighbor of any ancestor
00382         //    of nn is a component of this node, connect these two.
00383 
00384         hdyn * new_sister = nn;
00385         hdyn * root = get_root();
00386 
00387         // The nn of new_sister may be a node (see note above).  Take care
00388         // of this possibility before proceeding.  Expect that the nn is
00389         // the binary sister (should be the only way in which this can
00390         // occur -- see hdyn_ev), but do the search generally, anyway.
00391 
00392         hdyn *snn = new_sister->get_nn();
00393 
00394         if (snn && snn->is_valid() && !snn->is_leaf()) {
00395 
00396             // The true nn lies below snn.  Locate it, and modify
00397             // new_sister->nn accordingly.  Its distance should
00398             // be new_sister->d_nn_sq, but let's not tempt fate...
00399 
00400             real d_sq_min = VERY_LARGE_NUMBER;
00401             hdyn * local_nn = NULL;
00402             vector s_pos = hdyn_something_relative_to_root(new_sister,
00403                                                            &hdyn::get_pos);
00404 
00405             for_all_leaves(hdyn, snn, bb) {
00406                 vector b_pos = hdyn_something_relative_to_root(bb,
00407                                                                &hdyn::get_pos);
00408                 real d_sq = square(b_pos - s_pos);
00409                 if (d_sq < d_sq_min) {
00410                     local_nn = bb;
00411                     d_sq_min = d_sq;
00412                 }
00413             }
00414 
00415             if (local_nn) {
00416 
00417                 snn = local_nn;
00418                 new_sister->set_nn(snn);
00419 
00420                 if (diag->tree && diag->tree_level > 0) {
00421                     cerr << "new_sister_node:  computed local nn for "
00422                          << new_sister->format_label() << endl;
00423                     PR(local_nn);
00424                     cerr << "  (" << snn->format_label() << ")" << endl;
00425                     PRC(new_sister->get_d_nn_sq()); PRL(d_sq_min);
00426                 }
00427             }
00428         }
00429 
00430         // Attach to the highest possible ancestor of new_sister.
00431 
00432         if (snn && snn->is_valid() && common_ancestor(snn, this) != this) {
00433 
00434             hdyn* ns = new_sister;
00435 
00436             do {
00437                 new_sister = new_sister->get_parent();
00438             } while(new_sister != root
00439                     && new_sister->get_nn() != NULL
00440                     && new_sister->get_nn()->is_valid()
00441                     && new_sister->parent != parent
00442                     && common_ancestor(new_sister->get_nn(), this) != this);
00443 
00444             if (new_sister == root
00445                 || new_sister->get_nn() == NULL
00446                 || !new_sister->get_nn()->is_valid()
00447                 || new_sister->parent == parent
00448                 || common_ancestor(new_sister, this)== this
00449                 || common_ancestor(new_sister, this)== new_sister
00450                 ) return NULL;
00451 
00452             if (diag->tree && diag->tree_level > 0) {
00453                 cerr << "new_sister_node:  ascended tree from "
00454                      << ns->format_label();
00455                 cerr << " to " << new_sister->format_label() << endl;
00456             }
00457         }
00458 
00459         hdyn * ancestor = common_ancestor(this, new_sister);
00460 
00461         if (ancestor->is_root()) {
00462 
00463             top_level_combine = TRUE;
00464             return new_sister;
00465 
00466         } else {
00467 
00468             // The new sister node is in the same subtree.
00469             // Attach this node to the location as high up as possible.
00470 
00471             if (parent != ancestor) {
00472                 while (new_sister->get_parent() != ancestor) {
00473                     new_sister = new_sister->get_parent();
00474                 }
00475             }
00476 
00477             if (new_sister->kep == NULL) {
00478                 if (diag->tree && diag->tree_level > 0) {
00479                     cerr << "new sister node for "; pretty_print_node(cerr);
00480                     cerr << " (nn = "; nn->pretty_print_node(cerr);
00481                     cerr << ") is " ; new_sister->pretty_print_node(cerr);
00482                     PRI(2); PRL(top_level_combine);
00483                 }
00484                 return new_sister;
00485             }
00486         }
00487     }
00488     return NULL;
00489 }
00490 
00491 
00492 local void check_merge_esc_flags(hdyn *bi, hdyn *bj)
00493 {
00494     // Update any escaper flags in two nodes being combined.
00495     // The CM node is flagged as escaping iff both components are.
00496 
00497     bool iesc = find_qmatch(bi->get_dyn_story(), "t_esc");
00498     bool jesc = find_qmatch(bj->get_dyn_story(), "t_esc");
00499 
00500     if (iesc && jesc) {
00501 
00502         // Both components are flagged as escapers.
00503 
00504         real t_esc = max(getrq(bi->get_dyn_story(), "t_esc"),
00505                          getrq(bj->get_dyn_story(), "t_esc"));
00506         putrq(bi->get_parent()->get_dyn_story(), "esc", 1);
00507         putrq(bi->get_parent()->get_dyn_story(), "t_esc", t_esc);
00508 
00509     } else {
00510 
00511         // One component wasn't flagged as escaping.
00512 
00513         putrq(bi->get_parent()->get_dyn_story(), "esc", 0);
00514 
00515         if (iesc) {
00516             putrq(bi->get_dyn_story(), "esc", 0);
00517             rmq(bi->get_dyn_story(), "t_esc");
00518         }
00519 
00520         if (jesc) {
00521             putrq(bj->get_dyn_story(), "esc", 0);
00522             rmq(bj->get_dyn_story(), "t_esc");
00523         }
00524     }
00525 }
00526 
00527 void combine_top_level_nodes(hdyn * bj, hdyn * bi,
00528                              int full_dump)             // default = 0
00529 {
00530     // Combine two top-level nodes into a binary.  Original node names
00531     // and addresses are retained, so neighboring perturber lists are
00532     // unaffected.  bi is the node whose step caused the change; bj is
00533     // its nearest neighbor.  For obscure reasons, the new CM node
00534     // will be (bj, bi).
00535 
00536     if (bi->get_kira_diag()->tree) {
00537 
00538         cerr << endl << "combine_top_level_nodes: attaching ",
00539         bj->pretty_print_node(cerr);
00540         cerr << " to ", bi->pretty_print_node(cerr);
00541         cerr << " at time " << bi->get_system_time();
00542 
00543         if (bj->get_kira_diag()->tree_level > 0) {
00544 
00545             cerr << endl;
00546             pp2(bi, cerr);
00547             print_binary_from_dyn_pair(bj, bi);
00548             cerr << endl;
00549             if (bj->is_parent()) {
00550                 print_binary_from_dyn_pair(bj->get_oldest_daughter(),
00551                                            bj->get_oldest_daughter()
00552                                              ->get_younger_sister());
00553                 cerr << endl;
00554             }
00555             if (bi->is_parent()) {
00556                 print_binary_from_dyn_pair(bi->get_oldest_daughter(),
00557                                            bi->get_oldest_daughter()
00558                                              ->get_younger_sister());
00559                 cerr << endl;
00560             }
00561 
00562             if (bj->get_kira_diag()->tree_level > 1) {
00563 
00564                 // Not really necessary if pp3 (new node) occurs below:
00565                 //
00566                 // cerr << endl;
00567                 // pp3(bi, cerr);
00568                 // pp3(bj, cerr);
00569 
00570                 if (bj->get_kira_diag()->tree_level > 2) {
00571                     cerr << endl;
00572                     put_node(cerr, *bj, bj->get_kira_options()->print_xreal);
00573                     put_node(cerr, *bi, bi->get_kira_options()->print_xreal);
00574                 }
00575 
00576                 cerr << endl;
00577                 plot_stars(bj);
00578             }
00579 
00580         } else {
00581 
00582             cerr << endl << "                         ";
00583             print_relative_energy_and_period(bj, bi);
00584             cerr << endl;
00585         }
00586     }
00587 
00588     // Make sure bi and bj are up to date.
00589 
00590 
00591     predict_loworder_all(bi->get_root(), bi->get_system_time());
00592 
00593     // print_recalculated_energies(bi->get_root(), 1);
00594     // pp3((bi->get_root()), cerr);
00595     // synchronize_tree(bi->get_root(), time);
00596     // print_recalculated_energies(bi->get_root(), 1);
00597     // pp3((bi->get_root()), cerr);
00598 
00599     bi->synchronize_node();
00600     bj->synchronize_node();
00601 
00602     if (full_dump) {
00603 
00604         // Components are synchronized, but lower levels are not.
00605         // The 4tree software needs trees to be synchronous, but
00606         // synchronizing everything here will likely lead to runaway
00607         // timesteps.  Function put_node in this case must use
00608         // *predicted* quantities and system time as time.
00609         // All necessary predictions have already been done.)
00610 
00611         // Dump out the "before" system (bi and bj), for use in 4tree
00612         // applications, with "defunct" flags attached (final "3").
00613 
00614         // cerr << "combine_top_level_nodes: time " << bi->get_system_time();
00615         // cerr << "  put_node for " << endl << "    " << bi->format_label();
00616         // cerr << " and " << bj->format_label() << endl;
00617 
00618         put_node(cout, *bi, false, 3);
00619         put_node(cout, *bj, false, 3);
00620     }
00621 
00622     // Remove any slow_perturbed references to the components from
00623     // other top-level nodes.  Only possible if a component is a slow
00624     // binary...
00625 
00626     for (hdyn *bb = bi; bb != bj; bb = bj)
00627         if (bb->get_kappa() > 1) {
00628             hdyn *pnode = bb->find_perturber_node();
00629             if (pnode && pnode->get_valid_perturbers())
00630                 for (int k = 0; k < pnode->get_n_perturbers(); k++) {
00631                     hdyn *p = pnode->get_perturber_list()[k]
00632                                    ->get_top_level_node();
00633                     if (p->get_sp())
00634                         p->remove_slow_perturbed(bb);           
00635                 }
00636         }
00637 
00638     create_binary_from_toplevel_nodes(bi, bj);          // --> (bj, bi)
00639 
00640     // Copy any slow_perturbed lists to the new top-level node, and
00641     // delete the low-level lists.
00642 
00643     bi->copy_slow_perturbed(bi->get_parent());
00644     bi->clear_slow_perturbed();
00645     bj->copy_slow_perturbed(bj->get_parent());
00646     bj->clear_slow_perturbed();
00647 
00648     // Delete any slow_perturbed element in the new CM node that refers
00649     // to either component.
00650 
00651     if (bi->get_parent()->get_sp()) {
00652         bi->get_parent()->remove_slow_perturbed(bi);
00653         bi->get_parent()->remove_slow_perturbed(bj);
00654     }
00655 
00656     // Reset all perturber lists below the newly-formed top-level
00657     // node -- probably not necessary for bi and bj if low-level
00658     // perturber lists are allowed, but cleaner to clear and
00659     // recompute the lists.
00660 
00661     for_all_nodes(hdyn, bj->get_parent(), bb) {
00662         bb->set_valid_perturbers(false);
00663         bb->set_perturbation_squared(-1);
00664     }
00665 
00666     // Shrink timesteps for safety...
00667 
00668     // halve_timestep(bi);
00669     // halve_timestep(bj);
00670 
00671     halve_timestep(bj->get_parent());   // parent step should be less than the
00672                                         // daughter steps so that the parent
00673                                         // perturber list is computed before
00674                                         // the internal motion is advanced
00675 
00676     bi->init_pred();
00677     bj->init_pred();
00678     bj->get_parent()->init_pred();
00679 
00680     init_predictor_tree(bj->get_parent());      // for diagnostic output...
00681 
00682     check_merge_esc_flags(bj, bi);
00683 
00684     if (full_dump) {
00685 
00686         // Dump out the "after" system (parent), for use in 4tree
00687         // applications.  Must predict this portion of the tree again.
00688 
00689         predict_loworder_all(bj->get_parent(), bj->get_system_time());
00690 
00691         // cerr << "combine_top_level_nodes: time " << bi->get_system_time();
00692         // cerr << "  put_node for " << bj->get_parent()->format_label()
00693         //      << endl;
00694 
00695         put_node(cout, *bj->get_parent(), false, 2);
00696     }
00697 
00698     bi->get_kira_counters()->top_level_combine++;
00699 
00700     if (bi->get_kira_diag()->tree && bi->get_kira_diag()->tree_level > 1)
00701         pp3(bi->get_parent(), cerr);
00702 }
00703 
00704 void split_top_level_node(hdyn * bi,
00705                           int full_dump)        // default = 0
00706 {
00707     // Split a top-level node into two components.  The original node is
00708     // deleted, so any references to it (in nn/coll pointers or perturber
00709     // lists) must be corrected.
00710 
00711     if (!bi->is_top_level_node())
00712         err_exit("split_top_level_node: not at top level");
00713 
00714     if (bi->get_oldest_daughter()->get_slow()) {
00715 
00716         // Shouldn't happen -- flag and defer the split.
00717 
00718         cerr << "split_top_level_node: warning: trying to split slow binary "
00719              << bi->format_label() << endl
00720              << "    at time " << bi->get_system_time() << endl;
00721 
00722         // bi->get_oldest_daughter()->delete_slow();
00723 
00724         bi->get_oldest_daughter()->get_slow()->set_stop();
00725         return;
00726     }
00727 
00728     if (bi->get_kira_diag()->tree) {
00729 
00730         cerr << endl << "split_top_level_node: splitting ";
00731         bi->pretty_print_node(cerr);
00732         cerr << " at time " << bi->get_system_time();
00733 
00734         if (bi->get_kira_diag()->tree_level >= 1) {
00735             cerr << endl;
00736             pp2(bi, cerr);
00737             print_binary_from_dyn_pair(bi->get_oldest_daughter(),
00738                                        bi->get_oldest_daughter()
00739                                          ->get_younger_sister());
00740 
00741 #if 0
00742             cerr << endl;
00743             PRL(bi->get_oldest_daughter()->get_perturbation_squared());
00744             hdyn *pnode = bi->get_oldest_daughter()->find_perturber_node();
00745             if (pnode && pnode->is_valid()) {
00746                 PRL(pnode->format_label());
00747                 if (pnode->get_valid_perturbers())
00748                     PRL(pnode->get_n_perturbers());
00749                 else
00750                     cerr << "perturbers unknown" << endl;
00751             } else
00752                 cerr << "pnode invalid" << endl;
00753 #endif
00754 
00755 
00756             cerr << endl << flush;
00757 
00758             if (bi->get_kira_diag()->tree_level > 1) {
00759                 cerr << endl;
00760                 pp3(bi, cerr);
00761 
00762                 // Excessive output?
00763 
00764                 if (bi->get_kira_diag()->tree_level > 2)
00765                     put_node(cerr, *bi, bi->get_kira_options()->print_xreal);
00766             }
00767         } else {
00768             cerr << endl << "                      ";
00769             print_relative_energy_and_period(bi->get_oldest_daughter(),
00770                                              bi->get_oldest_daughter()
00771                                                ->get_younger_sister());
00772             cerr << endl;
00773         }
00774     }
00775 
00776     hdyn *od = bi->get_oldest_daughter();
00777     hdyn *yd = od->get_younger_sister();
00778 
00779     // Synchronize the nodes involved.
00780 
00781     predict_loworder_all(bi->get_root(), bi->get_system_time());
00782 
00783     // for debugging ...
00784     // synchronize_tree(bi->get_root());
00785     // synchronize_tree(bi);
00786 
00787     bi->synchronize_node();
00788     od->synchronize_node();
00789     update_binary_sister(od);
00790 
00791     if (full_dump) {
00792 
00793         // Components are synchronized, but lower levels are not.
00794 
00795         // Dump out the "before" system, for use in 4tree applications,
00796         // using predicted quantities.
00797 
00798         // cerr << "split_top_level_node: time " << bi->get_system_time();
00799         // cerr << "  put_node for " << bi->format_label() << endl;
00800 
00801         put_node(cout, *bi, false, 3);
00802     }
00803 
00804     // Express od and yd quantities relative to root.
00805 
00806     od->set_pos(hdyn_something_relative_to_root(od, &hdyn::get_pos));
00807     od->set_vel(hdyn_something_relative_to_root(od, &hdyn::get_vel));
00808     od->set_acc(hdyn_something_relative_to_root(od, &hdyn::get_acc));
00809     od->set_jerk(hdyn_something_relative_to_root(od, &hdyn::get_jerk));
00810     od->store_old_force();
00811 
00812     yd->set_pos(hdyn_something_relative_to_root(yd, &hdyn::get_pos));
00813     yd->set_vel(hdyn_something_relative_to_root(yd, &hdyn::get_vel));
00814     yd->set_acc(hdyn_something_relative_to_root(yd, &hdyn::get_acc));
00815     yd->set_jerk(hdyn_something_relative_to_root(yd, &hdyn::get_jerk));
00816     yd->store_old_force();
00817 
00818     od->init_pred();
00819     yd->init_pred();
00820 
00821     // May not be necessary to do this if low-level perturbers are
00822     // allowed, but cleaner to recompute the lists.  Clear all
00823     // perturber lists below the new top-level nodes.
00824 
00825     for_all_nodes(hdyn, od, bb) {
00826         bb->set_valid_perturbers(false);
00827         bb->set_perturbation_squared(-1);
00828     }
00829     for_all_nodes(hdyn, yd, bb) {
00830         bb->set_valid_perturbers(false);
00831         bb->set_perturbation_squared(-1);
00832     }
00833 
00834     // Dissolve the parent node and attach od and yd at top level.
00835 
00836     hdyn *root = bi->get_root();
00837 
00838     detach_node_from_general_tree(*bi);
00839 
00840     // Imperfect correction of neighbor pointers:
00841 
00842     if (bi->get_nn()->get_nn() == bi)
00843         bi->get_nn()->set_nn(NULL);
00844 
00845     // Should also check for the unlikely possibility that:
00846     //
00847     //  (1) binary bi is unperturbed, and
00848     //  (2) binary bi is on the perturber list of some other binary.
00849     //
00850     // If so, bi must be removed from the perturber list before being
00851     // deleted.
00852 
00853     if (!RESOLVE_UNPERTURBED_PERTURBERS)
00854         expand_perturber_lists(bi->get_root(), bi,
00855                                bi->get_kira_diag()->tree
00856                                    && bi->get_kira_diag()->tree_level > 0);
00857 
00858     // Copy any slow_perturbed list to the components.
00859 
00860     bi->copy_slow_perturbed(od, true);          // "true" ==> overwrite
00861     bi->copy_slow_perturbed(yd, true);
00862 
00863     delete bi;
00864 
00865     add_node(*od, *root);
00866     add_node(*yd, *root);
00867 
00868     // halve_timestep(od);
00869     // halve_timestep(yd);
00870 
00871     if (full_dump) {
00872 
00873         // Dump out the "after" system (od and yd), for use in 4tree
00874         // applications.
00875 
00876         predict_loworder_all(od, od->get_system_time());
00877         predict_loworder_all(yd, yd->get_system_time());
00878 
00879         // cerr << "split_top_level_node: time " << od->get_system_time();
00880         // cerr << "  put_node for " << endl << "    " << od->format_label();
00881         // cerr << " and " << yd->format_label() << endl;
00882 
00883         put_node(cout, *od, false, 2);
00884         put_node(cout, *yd, false, 2);
00885     }
00886 
00887     bi->get_kira_counters()->top_level_split++;
00888 }
00889 
00890 local void combine_low_level_nodes(hdyn * bi, hdyn * bj,
00891                                    int full_dump = 0)
00892 {
00893     // Rearrange the tree structure within a multiple system to try
00894     // to make bi and bj sister nodes.
00895 
00896     if (bi->get_slow()) {
00897 
00898         // Not sure if this can happen, but flag it just in case...
00899         // Hmmm, looks like it can happen (Steve, 9/00).
00900 
00901         // Old code:
00902         //
00903         // cerr << "combine_low_level_nodes: warning: splitting slow binary "
00904         //      << bi->get_parent()->format_label() << " at time "
00905         //      << bi->get_system_time()
00906         //      << endl;
00907         // bi->delete_slow();   // will likely cause a crash later!
00908 
00909         // New:
00910 
00911         // As in split_top_level_node, defer the split
00912         // and schedule the slow motion for termination...
00913 
00914         bi->get_slow()->set_stop();
00915         return;
00916     }
00917 
00918     if (bi->get_kira_diag()->tree && bi->get_kira_diag()->tree_level > 0) {
00919         cerr << "\ncombine_low_level_nodes:  combining ";
00920         bi->pretty_print_node(cerr);
00921         cerr << " and ";
00922         bj->pretty_print_node(cerr);
00923         cerr << " at time " << bi->get_system_time() << "\n";
00924     }
00925 
00926     hdyn *ancestor;
00927     ancestor = common_ancestor(bi, bj);
00928 
00929     bool pp3_at_end = false;
00930 
00931 #if 0
00932     if (bi->get_time() > 2.6 && bi->get_time() < 2.7) {
00933         cerr << endl << "------------------------------" << endl;
00934         cerr << "combine_low_level_nodes:" << endl;
00935         cerr << "bi = " << bi->format_label() << endl;
00936         cerr << "bj = " << bj->format_label() << endl;
00937         cerr << "ancestor = " << ancestor->format_label() << endl;
00938         pp3(ancestor);
00939         pp3_at_end = true;
00940     }
00941 #endif
00942 
00943     // Make sure bi and bj are up to date.
00944 
00945     predict_loworder_all(bi->get_root(), bi->get_system_time());
00946 
00947     bi->synchronize_node();
00948     bj->synchronize_node();
00949 
00950     synchronize_branch(bi, ancestor);
00951     synchronize_branch(bj, ancestor);
00952 
00953     hdyn* old_top_level_node = bi->get_top_level_node();
00954 
00955 //    if (full_dump == 1) {
00956     if (full_dump) {
00957 
00958         // Dump out the "before" system (top-level), for use in 4tree
00959         // applications.
00960 
00961         // cerr << "combine_low_level_nodes: time " << bi->get_system_time();
00962         // cerr << "  put_node for " << old_top_level_node->format_label()
00963         //      << endl;
00964 
00965         put_node(cout, *old_top_level_node, false, 3);
00966     }
00967 
00968     // Note from Steve, 3/99:
00969     //
00970     // Function move_node will remove the parent node of bi and
00971     // reattach node bi as a sister of bj.  If the binary sister
00972     // of bi is also a binary and contains bj, then it will become
00973     // an ancestor node of the new system.  If, as is likely, bi is
00974     // a perturber of its binary sister, the perturber list of the
00975     // new system will then be corrupted, as the ancestor node will
00976     // still contain bi as a perturber.  Avoid this unpleasantness
00977     // by forcing the perturber lists of the entire subtree to be
00978     // recomputed.  However, retain the top-level perturber list,
00979     // which should be unchanged, so we at least don't have to
00980     // compute perturbations using the entire system.
00981     // Messy, messy...
00982     //
00983     // Messier still, if bi's parent node happens to be the top-level
00984     // node, then the top-level node will be deleted and its perturber
00985     // information lost.  Save the perturber info and restore it to
00986     // the eventual top-level node.
00987 
00988     bool vp = old_top_level_node->get_valid_perturbers();
00989     int np = 0;
00990     real p_sq = -1;
00991     real p_fac = 0;
00992     hdyn** pert_list = NULL;
00993 
00994     if (vp) {
00995         np = old_top_level_node->get_n_perturbers();
00996         p_sq = old_top_level_node->get_perturbation_squared();
00997         p_fac = old_top_level_node->get_perturbation_radius_factor();
00998         pert_list = new hdyn *[MAX_PERTURBERS];
00999         for (int i = 0; i < np; i++)
01000             pert_list[i] = old_top_level_node->get_perturber_list()[i];
01001         // cerr << "saved top-level perturber information" << endl;
01002     }
01003 
01004     move_node(bi, bj);
01005 
01006     hdyn* top_level_node = bi->get_top_level_node();
01007 
01008     if (top_level_node != old_top_level_node) {
01009 
01010         if (vp) {
01011 
01012             // Restore original top-level perturbation information.
01013             // (Might have been easier simply to copy the node...)
01014 
01015             top_level_node->remove_perturber_list();
01016             top_level_node->new_perturber_list();
01017 
01018             top_level_node->set_valid_perturbers(vp);
01019             top_level_node->set_n_perturbers(np);
01020             top_level_node->set_perturbation_squared(p_sq);
01021             top_level_node->set_perturbation_radius_factor(p_fac);
01022 
01023             for (int i = 0; i < np; i++)
01024                 top_level_node->get_perturber_list()[i] = pert_list[i];
01025 
01026             delete pert_list;
01027             cerr << "restored top-level perturber information, np = "
01028                  << np << endl;
01029 
01030         } else {
01031 
01032             top_level_node->set_valid_perturbers(vp);
01033             top_level_node->set_perturbation_squared(-1);
01034 
01035         }
01036     }   
01037 
01038     // halve_timestep(bi);
01039     // halve_timestep(bj->get_parent());
01040 
01041     predict_loworder_all(bi->get_root(), bi->get_system_time());
01042 
01043     // Force all perturber lists in the present subtree to be rebuilt.
01044 
01045     for_all_nodes(hdyn, top_level_node, bb) {
01046         if (bb != top_level_node) {
01047 
01048             bb->set_valid_perturbers(false);
01049             bb->set_perturbation_squared(-1);
01050 
01051             // cerr << "cleared perturber lists for "
01052             //      << bb->format_label() << endl;
01053         }
01054     }
01055 
01056     bi->get_kira_counters()->low_level_combine++;
01057 
01058     // Make sure that all CM node names are up to date.
01059 
01060     hdyn *bn = bi->get_parent();
01061     while (bn != bi->get_root()) {
01062         label_binary_node(bn);
01063         bn = bn->get_parent();
01064     }
01065 
01066     check_merge_esc_flags(bi, bi->get_binary_sister());
01067 
01068 //    if (full_dump == 1) {
01069     if (full_dump) {
01070 
01071         // Dump out the "after" system (new top-level), for use in 4tree
01072         // applications.
01073 
01074         predict_loworder_all(top_level_node, bi->get_system_time());
01075 
01076         // cerr << "combine_low_level_nodes: time " << bi->get_system_time();
01077         // cerr << "  put_node for " << top_level_node->format_label() << endl;
01078 
01079         put_node(cout, *top_level_node, false, 2);
01080     }
01081 
01082     if (pp3_at_end) {
01083         cerr << endl << "after combine_low_level_nodes:" << endl;
01084         pp3(bi->get_top_level_node());
01085         cerr << endl << "------------------------------" << endl;
01086     }
01087 }
01088 
01089 local int adjust_low_level_node(hdyn * bi, int full_dump = 0)
01090 {
01091     int status = 1;
01092 
01093     bool top_level_combine;     // TRUE iff top-level nodes are to be combined.
01094                                 // Takes precedence over the returned value of
01095                                 // new_sister_node.  If new_sister_node is
01096                                 // non-NULL, it is the node which should become
01097                                 // the new sister of node bi within the same
01098                                 // binary subtree.
01099 
01100     hdyn *sister = bi->new_sister_node(top_level_combine);
01101 
01102 #if 0
01103     if (sister != NULL) {
01104         cout << "adjust low_level, "; bi->pretty_print_node(cout);
01105         cout << "-- "; sister->pretty_print_node(cout);
01106         cout << "-- "; sister->get_nn()->pretty_print_node(cout); cout<<endl;
01107     }
01108 #endif
01109 
01110     if (sister != NULL)
01111         predict_loworder_all(bi->get_root(), bi->get_system_time());
01112 
01113     if (top_level_combine) {
01114 
01115         if (number_of_daughter_nodes_exceeds(bi->get_root(), 2)) {
01116 
01117             if (bi->get_kira_diag()->tree
01118                     && bi->get_kira_diag()->tree_level > 1) {
01119                 cerr << "\nadjust_low_level_node: "
01120                      << "normal top level combine at time "
01121                      << bi->get_time() << endl;
01122                 // print_recalculated_energies(bi->get_root(), 1);
01123             }
01124 
01125             // cerr<< "Call combine_top_level_nodes from adjust_low_level_node"
01126             //     << endl;
01127 
01128             combine_top_level_nodes(sister->get_top_level_node(),
01129                                     bi->get_top_level_node(), full_dump);
01130             status = 2;
01131 
01132         } else {
01133 
01134             if (bi->get_kira_diag()->tree
01135                     && bi->get_kira_diag()->tree_level > 1) {
01136                 cerr << "adjust_low_level_node:"
01137                      << " top level combine with two top level nodes at time "
01138                      << bi->get_time() << endl;
01139                 // print_recalculated_energies(bi->get_root(), 1);
01140             }
01141 
01142             hdyn* t = bi->get_top_level_node();
01143             hdyn* od = t->get_oldest_daughter();
01144 
01145             if (!od)
01146                 status = 0;             // shouldn't happen
01147             else {
01148 
01149                 if (od->get_slow()) {
01150 
01151                     if (!od->get_slow()->get_stop()) {
01152                         cerr << "adjust_low_level_node: scheduling end "
01153                              << "of slow motion for " << bi->format_label()
01154                              << " at time " << bi->get_system_time()
01155                              << endl;
01156                         od->get_slow()->set_stop();
01157                     }
01158                     status = 0;
01159 
01160                 } else {
01161 
01162                     // cerr << "call split_top_level_node 1" << endl;
01163 
01164                     split_top_level_node(t, full_dump);
01165                     status = 3;
01166 
01167                 }
01168             }
01169         }
01170 
01171     } else if (sister != NULL)
01172 
01173         combine_low_level_nodes(bi, sister, full_dump);
01174 
01175     else
01176 
01177         status = 0;
01178 
01179     return status;
01180 }
01181 
01182 
01183 local inline bool check_binary_params(hdyn *b)
01184 {
01185     if (b->is_low_level_node()) {
01186 
01187         hdyn *od = b->get_oldest_daughter();
01188 
01189         if (od                                          // b is a low-level,
01190             && od->get_perturbation_squared() > 1) {    // strongly perturbed,
01191                                                         // binary node
01192 
01193             bool sync = false;
01194             int reason = 0;
01195 
01196             if (od->get_timestep()                      // very disparate
01197                     > 128*b->get_timestep())            // component timesteps
01198                                                         // (128 is arbitrary)
01199                 sync = true;
01200 
01201             else if (b->distance_to_sister_squared()    // components are too
01202                      < od->distance_to_sister_squared() // far apart, with some
01203                     && od->get_timestep()               // timestep disparity
01204                         > 4*b->get_timestep()) {        // (4 is arbitrary)
01205 
01206                 sync = true;
01207                 reason = 1;
01208 
01209             }
01210 
01211             // Synchronize the binary components if they are not on the
01212             // current integration list, and reset the binary timestep
01213             // to match the parent node.
01214 
01215             if (od->get_time() == b->get_time()) sync = false;
01216 
01217             if (sync) {
01218 
01219                 od->synchronize_node();
01220                 od->set_timestep(b->get_timestep());
01221 
01222                 if (b->get_kira_diag()->tree
01223                     && b->get_kira_diag()->tree_level > reason)
01224                     cerr << "check_binary_params: synchronizing ("
01225                          << reason << ") "
01226                          << b->format_label() << " components at time "
01227                          << b->get_system_time() << endl;
01228 
01229                 return true;
01230             }
01231         }
01232     }
01233 
01234     return false;
01235 }
01236 
01237 local void print_tree_structure(hdyn *bb)               // for debugging
01238 {
01239     hdyn *b = bb->get_top_level_node();
01240     hdyn *od = b->get_oldest_daughter();
01241 
01242     if (od) {
01243         hdyn *yd = od->get_younger_sister();
01244 
01245         cerr << endl << "tree structure for " << b->format_label()
01246              << " at time " << b->get_system_time() << endl;
01247         cerr << "output triggered by " << bb->format_label() << endl;
01248 
01249         // Daughters:
01250 
01251         cerr << "daughters are " << od->format_label() << " and ";
01252         cerr << yd->format_label();
01253         cerr << ", separation = " << abs(od->get_pos()-yd->get_pos()) << endl;
01254         cerr << "daughter neighbors are " << od->get_nn()->format_label()
01255              << " and ";
01256         cerr << yd->get_nn()->format_label() << endl;
01257 
01258         // Granddaughters:
01259 
01260         for_all_daughters(hdyn, b, d) {                 // d is od or yd
01261             hdyn *od1 = d->get_oldest_daughter();
01262             if (od1) {
01263                 cerr << "    daughters of " << d->format_label();
01264                 hdyn *od2 = od1->get_younger_sister();
01265                 cerr << " (separation = "
01266                      << abs(od1->get_pos()-od2->get_pos()) << "):" << endl;
01267                 hdyn *s = d->get_binary_sister();
01268                 for_all_daughters(hdyn, d, dd) {        // dd is od1 or od2
01269                     if (s->is_parent()) {
01270                         for_all_daughters(hdyn, s, ss) {
01271                             cerr << "        distance from "
01272                                  << dd->format_label();
01273                             cerr << " to " << ss->format_label() << " is ";
01274                             cerr << abs(d->get_pos()+dd->get_pos()
01275                                         -s->get_pos()-ss->get_pos())
01276                                  << endl;
01277                         }
01278                     } else {
01279                         cerr << "        distance from " << dd->format_label();
01280                         cerr << " to " << s->format_label() << " is ";
01281                         cerr << abs(d->get_pos()+dd->get_pos()-s->get_pos())
01282                              << endl;
01283                     }
01284                 }
01285             }
01286         }
01287     }   
01288 }
01289 
01290 int hdyn::adjust_tree_structure(int full_dump)          // default = 0
01291 {
01292     int status = 0;
01293 
01294     // Value of status (return value) indicates adjustment that occurred:
01295     //
01296     //          0       no adjustment
01297     //          1       low-level combine
01298     //          2       top-level combine (direct)
01299     //          3       top-level split (direct)
01300     //          4       top-level combine (indirect)
01301     //          5       top-level split (indirect)
01302     //          6       low-level timestep change (no tree change)
01303     //
01304     // (Similar coding also applies to adjust_low_level_node.)
01305 
01306     // cerr << "\n*** in adjust_tree_structure for " << format_label() << endl;
01307 
01308     hdyn *br = get_root();
01309     if (is_top_level_node()) {          // this is a top-level node
01310 
01311         bool cm = false;
01312         if (oldest_daughter) cm = true;
01313 
01314         if (nn == NULL) {
01315             pretty_print_node(cerr); cerr << " nn is NULL " << endl;
01316             return 0;
01317         }
01318 
01319         hdyn *nn_top = nn->get_top_level_node();
01320 
01321         if (too_close(this, nn_top, d_min_sq)) {
01322 
01323             if (number_of_daughter_nodes_exceeds(parent, 2)) {
01324 
01325                 predict_loworder_all(get_root(), system_time);
01326 
01327                 // cerr << "\ntime = " << system_time << endl;
01328                 // print_recalculated_energies(get_root(), 1);
01329                 // pp3(get_root(), cerr);
01330 
01331                 // cerr << "Call combine_top_level_nodes from "
01332                 //      << "adjust_tree_structure"<<endl;
01333 
01334                 combine_top_level_nodes(nn_top, this, full_dump);
01335 
01336                  // cerr << "Time = " << system_time<< endl;
01337                  // print_recalculated_energies(get_root(), 1);
01338                  // pp3(get_root(), cerr);
01339 
01340                 status = 2;
01341 
01342             } else {
01343 
01344                 status = 0;
01345             }
01346 
01347         } else if (too_big(this, d_min_sq * lag_factor)) {
01348 
01349             // print_recalculated_energies(get_root(), 1);
01350 
01351             predict_loworder_all(get_root(), system_time);
01352 
01353             // Don't check for slow binary, as too_big should return false
01354             // if this is slow.
01355 
01356             // cerr << "call split_top_level_node 2" << endl;
01357 
01358             split_top_level_node(this, full_dump);
01359 
01360             // Better exit next -- 'this' has already been deleted...
01361 
01362             status = 3;
01363 
01364         } else {
01365 
01366             status = 0;
01367         }
01368 
01369     } else {                    // this is a low-level node
01370                                 // *** check both this and our sister ***
01371         if (kep == NULL) {
01372 
01373             hdyn *s = get_binary_sister();
01374             hdyn *old_top_level_node = get_top_level_node();
01375 
01376             status = adjust_low_level_node(this, full_dump);
01377             if (!status) status = adjust_low_level_node(s, full_dump);
01378 
01379             if (status) {
01380 
01381                 if (status > 1) status += 2;
01382                 if (old_top_level_node != get_top_level_node())
01383                     get_top_level_node()->zero_perturber_list();
01384 
01385             } else {
01386 
01387                 // Check sizes of low-level binaries.  In some circumstances
01388                 // it is possible for the center of mass timestep of a
01389                 // binary to become very small as its components recede,
01390                 // with the result that the binary is never split up.
01391                 // Explicitly attempt to avoid that here (Steve, 6/00).
01392 
01393                 if (check_binary_params(this) || check_binary_params(s))
01394                     status = 6;
01395             }
01396 
01397 #if 0
01398             if (system_time > 2295.905
01399                 && node_contains(get_top_level_node(), "9530"))
01400                 print_tree_structure(this);
01401 #endif
01402 
01403         } else {
01404 
01405             status = 0;
01406         }
01407     }
01408 
01409     return status;
01410 }

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