Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

hdyn_slow.C

Go to the documentation of this file.
00001 
00002        //=======================================================//    _\|/_
00003       //  __  _____           ___                    ___       //      /|\ ~
00004      //  /      |      ^     |   \  |         ^     |   \     //          _\|/_
00005     //   \__    |     / \    |___/  |        / \    |___/    //            /|\ ~
00006    //       \   |    /___\   |  \   |       /___\   |   \   // _\|/_
00007   //     ___/   |   /     \  |   \  |____  /     \  |___/  //   /|\ ~
00008  //                                                       //            _\|/_
00009 //=======================================================//              /|\ ~
00010 
00011 // Initiate, extend, or terminate slow binary motion.
00012 //
00013 // Externally visible functions:
00014 //
00015 //      void hdyn::startup_slow_motion
00016 //      void hdyn::extend_or_end_slow_motion
00017 //      bool has_binary_perturbers
00018 //      void check_slow_consistency
00019 //      void clear_perturbers_slow_perturbed
00020 //
00021 // Note from Steve, 8/99:
00022 //
00023 // Slow binary motion is handled by two data classes:
00024 //
00025 // 1. Slow motion itself is signified simply by attaching a slow_binary
00026 //    pointer to the binary components (the data structure is shared
00027 //    by the two components).  If the slow pointer is set, the binary
00028 //    time scale is reduced by a slowdown factor kappa (i.e. dtau =
00029 //    dt/kappa), and the perturbation is increased by the same factor.
00030 //    The motion *must* continue for an integral number of orbits (see
00031 //    Mikkola & Aarseth); it is reassessed for extension or termination
00032 //    at the same phase (just after apocenter) of every orbit.  The
00033 //    transition to unperturbed motion is handled by attaching a flag
00034 //    indicating that the motion must terminate at the proper phase;
00035 //    subsequently, unperturbed motion can begin normally.  This portion
00036 //    of the motion is straightforward to program and maintain.
00037 //
00038 // 2. However, once a binary is undergoing slow motion, its center of
00039 //    mass motion and its effect on its perturbers require special
00040 //    attention.  The reason is that the internal motion causes a
00041 //    "ripple" in the CM and external acc and jerk, and this must be
00042 //    handled self-consistently.  When the internal motion is slowed, the
00043 //    computed acc and jerk felt by the CM and its neighbors are not
00044 //    consistent with the actual time development of the internal motion,
00045 //    leading to large k (= j') and l (= j'') derivatives and excessively
00046 //    short timesteps.  In fact, the opposite should be the case: the
00047 //    slowed motion should *reduce* the ripple, allowing the CM and
00048 //    neighbor steps to increase.  The corrector now treats interactions
00049 //    involving slow binaries separately, reducing the relevant a, j, k,
00050 //    and l by factors of kappa, kappa^2, etc., and does in fact allow
00051 //    longer timesteps for the CM and perturber motion.
00052 //
00053 //    This portion of kira is significantly messier to code and maintain
00054 //    than the slow motion itself.  The CM motion and perturber motion
00055 //    are handled differently (and both are presently implemented only
00056 //    for top-level nodes):
00057 //
00058 //      * For the CM, instead of correcting the center of mass force
00059 //        for the perturbation due to perturbers, we instead store the
00060 //        perturbative part as acc_p and jerk_p in the slow_binary
00061 //        structure attached to the *daughter* nodes.  Function
00062 //        store_old_force also maintains old_acc_p and old_jerk_p in
00063 //        this structure.  The corrector computes the higher
00064 //        derivatives separately for the pertubative term, taking the
00065 //        slowdown factors into account, and then combines it with the
00066 //        usual correction terms.
00067 //
00068 //      * For perturbers of a slow binary, things are more complex, as
00069 //        the correction in principle is different for each slow
00070 //        binary a particle happens to perturb.  Presently, I (Steve)
00071 //        see no alternative to storing acc_p and jerk_p separately
00072 //        (and maintaining the old_ versions) for every slow binary a
00073 //        node perturbs.  Then, in the corrector phase, the high
00074 //        derivatives are computed separately for each slow binary
00075 //        interaction and combined into the total.  The acc_p and
00076 //        jerk_p terms for each binary, together with other data
00077 //        needed to manage them, are stored in the structure
00078 //        slow_perturbed, arranged as a linked list attached to the
00079 //        *top-level* node of the perturber (since the correction is
00080 //        applied only to the motion of the top-level node, this seems
00081 //        the most natural place to store the information).  The
00082 //        structure also contains a pointer to the *center of mass*
00083 //        node of the slow binary in question.  Relevant list elements
00084 //        are deleted each time the slow binary's perturber list is
00085 //        recomputed, and when slow motion ends.
00086 //
00087 // The procedures just described are currently implemented only for
00088 // top-level nodes, principally because the perturbative component of
00089 // the interparticle force is easy to determine in that case (since all
00090 // forces on top-level nodes are initially computed in the center of
00091 // mass approximation and the correction is easily absorbed into
00092 // correct_acc_and_jerk).  It probably is possible to apply similar
00093 // corrections for low-level binaries (e.g. in a triple), but these have
00094 // not yet been implemented.  They probably should be implemented at
00095 // least for binary sisters (to allow for, e.g. a triple containing a
00096 // weakly perturbed binary).  For low-level slow binaries, it may be
00097 // sufficient to use the kepler timestep criterion and avoid any further
00098 // correction...  (Note that slow motion can always be applied; only the
00099 // application of interparticle force corrections are affected.)
00100 //
00101 // Current conventions:
00102 //
00103 //      - slow motion may be applied to binaries at any level
00104 //
00105 //      - slow corrections are applied only to top-level nodes, so
00106 //        only top-level nodes should have slow_perturbed lists, and
00107 //        low-level binaries should not appear on those lists
00108 //
00109 //      - corrections to triple/multiple components are *not* yet
00110 //        implemented -- see hdyn_ev.C (correct_and_update)
00111 //
00112 //        *** probably will use the slow binary structure attached ***
00113 //        *** to the (elder) binary component to implement this... ***
00114 //
00115 // The slow and slow_perturbed classes are defined in _dyn_.h and managed
00116 // in _dyn_slow.C.  The only use is in kira, accessed via this file.
00117 
00118 #include "hdyn.h"
00119 #include "hdyn_inline.C"
00120 
00121 bool has_binary_perturbers(hdyn* b)
00122 {
00123     // Assume b is a low-level node (or a binary node) on entry.
00124 
00125     hdyn *pnode = b->find_perturber_node();
00126 
00127     if (pnode == NULL || !pnode->get_valid_perturbers()) {
00128 
00129         // Really should check that another binary exists somewhere in
00130         // the system, but this test is used to permit slow motion,
00131         // and pnode must exist in any case for that to happen.
00132 
00133         return true;
00134     }
00135 
00136     // See if any perturber is a binary CM or binary component.
00137     // Probably OK to allow unperturbed binaries to be perturbers, as
00138     // they will be handled in the CM approximation, but exclude them
00139     // for now.
00140 
00141     for (int k = 0; k < pnode->get_n_perturbers(); k++) {
00142         hdyn * p = pnode->get_perturber_list()[k];
00143         if (p->is_parent() || p->is_low_level_node()) return true;
00144     }
00145 
00146     return false;
00147 }
00148 
00149 // Store {2^k}^{1/3} in a fixed-length array (limits the slowdown factor
00150 // to a maximum of 10^6!).  Array length is defined in kira_counters,
00151 // but we insert an extra entry for kappa = 1 at the start.
00152 
00153 static real k3[SLOW_BINS+1] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
00154 
00155 local void set_k3()
00156 {
00157     int k2 = 1;
00158     for (int k = 0; k < SLOW_BINS; k++) {
00159         k3[k] = pow(k2, 1.0/3);
00160         k2 *= 2;
00161     }
00162 }
00163 
00164 local int get_slowdown_factor(hdyn* bi, real P = 0)
00165 {
00166     // Initialize the local array.
00167 
00168     if (*k3 == 0) set_k3();
00169 
00170     // Require a valid list of perturbers.  Note that this will cause
00171     // existing slow motion to be terminated if no valid list is found.
00172 
00173     hdyn* pnode = bi->find_perturber_node();
00174 
00175     if (pnode == NULL || !pnode->get_valid_perturbers()) return -1;
00176 
00177     // if (has_binary_perturbers(bi)) return 0;
00178 
00179     // Estimate the number of orbital periods before the external
00180     // perturbation becomes unacceptably high, and set the binary
00181     // slowdown factor accordingly.
00182 
00183     // Don't use apert/jpert, since this is sensitive to the very
00184     // suborbital "wiggles" we are trying to average away!
00185 
00186     if (P <= 0)
00187         P = get_period(bi, bi->get_younger_sister());
00188 
00189     if (P <= 0 || P == VERY_LARGE_NUMBER) return -1;    // redundant...
00190 
00191     // Procedure: we can set the slowdown level to kappa if no member of
00192     // the perturber list will become a "kappa-perturber," with
00193     //
00194     //          kappa * perturbation  >  max_slow_perturbation
00195     //
00196     // during the next kappa orbits (i.e. in time kappa * P).  For each
00197     // perturber we compute the maximum permissible kappa.  The returned
00198     // value is the minimum of these kappa values.
00199 
00200     int kappa = bi->get_max_slow_factor();
00201 
00202     hdyn *par = bi->get_parent();
00203     real scale = binary_scale(par);     // "size" of the binary
00204 
00205     // Absolute pos, vel, and acc of the binary's top-level node:
00206 
00207     hdyn *top = bi->get_top_level_node();
00208     vector tpos = top->get_pred_pos();
00209     vector tvel = top->get_pred_vel();
00210     vector tacc = top->get_acc();
00211 
00212     // Loop over perturbers.
00213 
00214     for (int i = 0; i < pnode->get_n_perturbers(); i++) {
00215 
00216         hdyn *bj = pnode->get_perturber_list()[i];
00217 
00218         // Compute the critical separation corresponding to the maximum
00219         // allowed "slow" perturbation.  Note that, for some perturber
00220         // options, this quantity is independent of the perturber.
00221         // Live with that inefficiency (for now, at least).
00222 
00223         real rpert3 = crit_separation_cubed(par,
00224                                             bj->get_mass(),
00225                                             scale,
00226                                             bi->get_max_slow_perturbation());
00227 
00228         real rpert = pow(rpert3, 1.0/3);        // live with this too...
00229 
00230         // (Note that rpert3 scales as 1 / gamma; hence the k3 = k^{1/3}
00231         // factor below.)
00232 
00233         // Compute relative pos, vel, and acc for use in the perturber
00234         // timescale estimates below.  Use top-level nodes if they are
00235         // different, in order to remove all internal motion from the
00236         // calculation.  If bi and bj are in the same clump, use par
00237         // and its binary sister in the calculation.
00238 
00239         vector dpos = 0, dvel = 0, dacc = 0;
00240 
00241         hdyn *jtop = bj->get_top_level_node();
00242 
00243         if (jtop != top) {
00244             dpos = tpos - jtop->get_pred_pos();
00245             dvel = tvel - jtop->get_pred_vel();
00246             dacc = tacc - jtop->get_acc();
00247         } else {
00248             hdyn *sis = par->get_binary_sister();
00249             dpos = par->get_pos() - sis->get_pos();
00250             dvel = par->get_vel() - sis->get_vel();
00251             dacc = par->get_acc() - sis->get_acc();
00252         }
00253 
00254         real dr = abs(dpos);
00255         real vr = dvel * dpos / dr;
00256         real ar = dacc * dpos / dr;
00257 
00258         // Loop over k2 (= 2^k) and
00259         //
00260         //      1. determine the distance at which bj would be a
00261         //         k2-perturber of pnode,
00262         //      2. estimate the time needed for bj to reach that
00263         //         radius,
00264         //      3. stop when that time is less than k2*P.
00265 
00266         int k = 0, k2 = 1;
00267         while (k2 <= kappa) {
00268 
00269             if (time_to_radius(dr - rpert * k3[k], vr, ar) < k2 * P)
00270                 break;
00271 
00272             k++;
00273             k2 *= 2;
00274         }
00275 
00276         kappa = min(kappa, k2/2);
00277         if (kappa < 2) break;   
00278     }
00279 
00280     // *** Should we limit the slowdown increment to a factor of 2? ***
00281 
00282     return kappa;
00283 }
00284 
00285 // We could probably incorporate startup_slow_motion() into
00286 // extend_or_end_slow_motion(), but leave the two functions
00287 // separate for now...
00288 
00289 void hdyn::startup_slow_motion()
00290 {
00291     int k = get_slowdown_factor(this);
00292 
00293     if (k > 1) {
00294 
00295         create_slow(k);
00296 
00297         // Possibly should expand the perturber list to allow for
00298         // the slowdown factor, but that would increase the cost per
00299         // step and undo the benefit of the slowdown.  Assume for
00300         // now that we can ignore the extra weak perturbers so long
00301         // as we carry out this procedure one orbit at a time.
00302 
00303         if (diag->slow) {
00304             cerr << endl
00305                  << "starting slow motion for "
00306                  << get_parent()->format_label()
00307                  << " at time " << get_time()
00308                  << "; kappa = " << get_kappa()
00309                  << endl;
00310             cerr << "    perturbation = " << sqrt(perturbation_squared)
00311                  << endl
00312                  << "    timestep = " << timestep
00313                  << "  parent timestep = " << get_parent()->timestep
00314                  << endl;
00315             if (get_parent()->get_nn())
00316                 cerr << "    nn of parent = "
00317                      << get_parent()->get_nn()->format_label() << endl;
00318         }
00319 
00320         // Update slow_perturbed lists, if this is a top-level binary.
00321 
00322         hdyn *par = get_parent();
00323         if (par->is_top_level_node()) {
00324 
00325             // Set/reset the slow_perturber lists of all perturbers,
00326             // to pass consistency checks elsewhere in the code.
00327 
00328             hdyn *pnode = find_perturber_node();
00329 
00330             if (!pnode || !pnode->get_valid_perturbers()) {
00331 
00332                 // No perturber node?  Shouldn't happen, since this is a
00333                 // prerequisite for slow motion to begin...
00334 
00335                 cerr << "startup_slow_motion: "
00336                      << "no valid perturber node for new slow binary "
00337                      << get_parent()->format_label() << endl;
00338 
00339             } else {
00340 
00341                 if (diag->slow)
00342                     cerr << "    perturber node is " << pnode->format_label()
00343                          << "  n_perturbers = " << pnode->get_n_perturbers()
00344                          << endl;
00345 
00346                 for (int j = 0; j < pnode->get_n_perturbers(); j++) {
00347 
00348                     hdyn *pert_top = pnode->get_perturber_list()[j]
00349                                           ->get_top_level_node();
00350 
00351                     // Only consider perturbers outside the present clump.
00352                     // (This test isredundant if we limit the slow_perturbed
00353                     // treatment to top-level binaries only.)
00354 
00355                     if (pert_top != par) {
00356 
00357                         slow_perturbed *s = pert_top->find_slow_perturbed(par);
00358                         if (!s)
00359                             s = pert_top->add_slow_perturbed(par,
00360                                                          diag->slow_perturbed);
00361 
00362                         if (diag->slow && diag->slow_level > 0)
00363                             cerr << "    updated slow_perturbed list"
00364                                  << " of top-level node "
00365                                  << pert_top->format_label() << endl;
00366                     }
00367                 }
00368             }
00369         }
00370     }
00371 }
00372 
00373 static char* term_reason[4] = {"forced",           // set_stop
00374                                "invalid plist",    // get_slowdown_factor = -1
00375                                "binary perturber", // get_slowdown_factor =  0
00376                                "perturbed"};       // get_slowdown_factor =  1
00377 
00378 void hdyn::extend_or_end_slow_motion(real P)    // convenient to pass P (!)
00379                                                 // as an optional argument
00380 {
00381     int k = -2, old_k = get_kappa();
00382 
00383     if (!slow->get_stop())
00384         k = get_slowdown_factor(this, P);
00385 
00386     if (k > 1) {
00387 
00388         // Extend the slow motion.
00389 
00390         if (k != old_k) {
00391 
00392             // Modify the value of kappa.
00393 
00394             extend_slow(k);
00395 
00396             // Notify all perturbers that kappa has changed.
00397 
00398             hdyn *par = get_parent();
00399             if (par->is_top_level_node()) {
00400 
00401                 hdyn *pnode = find_perturber_node();
00402                 if (pnode && pnode->get_valid_perturbers()) {
00403 
00404                     for (int j = 0; j < pnode->get_n_perturbers(); j++) {
00405 
00406                         hdyn *pert_top = pnode->get_perturber_list()[j]
00407                                               ->get_top_level_node();
00408 
00409                         if (pert_top != par) {
00410 
00411                             slow_perturbed *s = pert_top
00412                                                   ->find_slow_perturbed(par);
00413                             if (!s)
00414                                 s = pert_top->add_slow_perturbed(par,
00415                                                        diag->slow_perturbed);
00416 
00417                             s->set_kappa(k);
00418 
00419                             if (diag->slow && diag->slow_level > 0)
00420                                 cerr << "    updated slow_perturbed list of"
00421                                      << " top-level node "
00422                                      << pert_top->format_label() << endl;
00423                         }
00424                     }
00425                 }
00426             }
00427 
00428         } else
00429 
00430             // Accept the current time as the new apocenter time
00431             // (already done by extend_slow in other case).
00432 
00433             slow->set_t_apo(get_time());
00434 
00435         if (diag->slow && (diag->slow_level > 0 || k != old_k))
00436             cerr << endl
00437                  << "extending slow motion for "
00438                  << get_parent()->format_label()
00439                  << " at time " << get_time()
00440                  << "; new kappa = " << get_kappa()
00441                  << endl;
00442 
00443     } else {
00444 
00445         // End the slow motion: first correct the slow_perturbed lists of
00446         // all perturbers, if necessary, then delete the slow structure.
00447 
00448         hdyn *par = get_parent();
00449 
00450         if (diag->slow)
00451             cerr << endl
00452                  << "ending slow motion for "
00453                  << par->format_label()
00454                  << " at time " << get_time()
00455                  << " (" << term_reason[k+2] << ")"
00456                  << endl;
00457 
00458         if (par->is_top_level_node()) {
00459 
00460             hdyn *pnode = find_perturber_node();
00461 
00462             if (pnode && pnode->get_valid_perturbers())
00463                 for (int j = 0; j < pnode->n_perturbers; j++) {
00464                     hdyn *pert_top = pnode->perturber_list[j]
00465                                           ->get_top_level_node();
00466 
00467                     if (pert_top != par) {
00468 #if 0
00469                         cerr << "correcting slow_perturbed list of "
00470                              << pert_top->format_label() << endl;
00471 #endif
00472                         pert_top->remove_slow_perturbed(par,
00473                                                         diag->slow_perturbed);
00474                     }
00475                 }
00476         }
00477 
00478         delete_slow();
00479     }
00480 }
00481 
00482 void clear_perturbers_slow_perturbed(hdyn * b)
00483 {
00484     // Clear slow binary b from the slow_perturbed lists of all
00485     // of its perturbers.
00486 
00487     if (b->get_valid_perturbers())
00488         for (int j = 0; j < b->get_n_perturbers(); j++) {
00489             hdyn * pert_top = b->get_perturber_list()[j]
00490                                ->get_top_level_node();
00491 #if 0
00492             cerr << "removing " << b->format_label();
00493             cerr << " from slow_perturbed list of "
00494                  << pert_top->format_label()
00495                  << endl;
00496 #endif
00497             pert_top->remove_slow_perturbed(b, b->get_kira_diag()
00498                                                 ->slow_perturbed);
00499         }
00500 }
00501 
00502 void list_slow_perturbed(hdyn *b)
00503 {
00504     // Print slow_perturbed data on all nodes below (and including) b.
00505 
00506     bool found = false;
00507 
00508     for_all_nodes(hdyn, b, bb) {
00509         slow_perturbed *s = bb->get_sp();
00510         if (s) {
00511             found = true;
00512             bb->dump_slow_perturbed("    ");
00513         }
00514     }
00515 
00516     if (!found)
00517         cerr << "    no slow_perturbed data found for "
00518              << b->format_label() << endl;
00519 }
00520 
00521 void check_slow_consistency(hdyn *b)
00522 {
00523     // Perform basic checks of slow and slow_perturber data structures.
00524     //
00525     //      1. Check that all slow_perturber lists contain valid entries:
00526     //
00527     //          - only top-level nodes should have slow_perturbed lists
00528     //          - no duplicate entries
00529     //          - node pointer points to a valid node
00530     //          - node pointer points to a slow binary node
00531     //          - node pointer points to a slow binary perturbed
00532     //            by 'this' node
00533     //          - 'this' kappa agrees with node kappa
00534     //
00535     //      2. Check that each perturber of a top-level slow binary
00536     //         contains the slow binary on its slow_perturber list.
00537     //
00538     // Do not perform corrections if problems are found -- report only.
00539 
00540     // First check slow_perturber lists.
00541 
00542     hdyn *root = b->get_root();
00543 
00544     for_all_nodes(hdyn, b, bi) {
00545         if (bi != root) {
00546 
00547             slow_perturbed *s = bi->get_sp();
00548 
00549             // Check for illegal pointers.
00550 
00551             if (s && !bi->is_top_level_node())
00552                 cerr << "check_slow_consistency: low-level node "
00553                      << bi->format_label() << " has a slow_perturbed pointer"
00554                      << endl;
00555 
00556             // Check for duplicates.
00557 
00558             while (s) {
00559                 slow_perturbed *s1 = s->get_next();
00560                 while (s1) {
00561                     if (s1->get_node() == s->get_node()) {
00562                         cerr << "check_slow_consistency: node "
00563                              << s->get_node()->format_label()
00564                              << " (" << s->get_node()
00565                              << ")" << endl;
00566                         cerr << "                        "
00567                              << "duplicated on slow_perturbed list of "
00568                              << bi->format_label() << endl;
00569                     }
00570                     s1 = s1->get_next();
00571                 }
00572                 s = s->get_next();
00573             }
00574 
00575             // Then apply basic consistency checks to top-level nodes only.
00576 
00577             if (bi->is_top_level_node()) {
00578 
00579                 s = bi->get_sp();
00580 
00581                 while (s) {
00582 
00583                     hdyn *pert_node = (hdyn*)s->get_node();
00584 
00585                     if (!is_valid_slow(pert_node)       // checks valid and slow
00586                         || !pert_node->is_top_level_node()) {
00587 
00588                         cerr << "check_slow_consistency: node "
00589                              << pert_node->format_label()
00590                              << " (" << pert_node
00591                              << ")" << endl;
00592                         cerr << "                        "
00593                              << "on slow_perturbed list of "
00594                              << bi->format_label() << endl
00595                              << "                        "
00596                              << "is ";
00597                         if (!pert_node->is_valid())
00598                             cerr << "invalid";
00599                         else if (pert_node->is_top_level_node())
00600                             cerr << "not a slow binary CM";
00601                         else
00602                             cerr << "not a top-level binary";
00603                         cerr << " at time " << b->get_system_time() << endl;
00604 
00605                     } else {
00606 
00607                         // Pert_node is a valid slow top-level binary.
00608                         // Check that bi (or a component) perturbs it.
00609 
00610                         // Note that find_perturber_node starts checking at
00611                         // the parent level...
00612 
00613                         hdyn *pnode = pert_node->get_oldest_daughter()
00614                                                ->find_perturber_node();
00615                         if (!pnode) {
00616 
00617                             cerr << "check_slow_consistency: no perturber node"
00618                                  << " for " << pert_node->format_label()
00619                                  << " (" << pert_node << ")"
00620                                  << endl;
00621                             cerr << "                        "
00622                                  << "on slow_perturbed list of "
00623                                  << bi->format_label()
00624                                  << endl;
00625                             cerr << "                        "
00626                                  << "at time " << b->get_system_time()
00627                                  << endl;
00628 
00629                         } else {
00630 
00631                             // Convention is that binaries are resolved into
00632                             // components (unless unperturbed) on perturber
00633                             // lists, but the slow_perturbed list is attached
00634                             // to the top-level node of the perturber and points
00635                             // to the center of mass node of the slow binary.
00636 
00637                             bool found = false;
00638                             for (int k = 0;
00639                                  k < pnode->get_n_perturbers(); k++) {
00640                                 hdyn* pk_top = pnode->get_perturber_list()[k]
00641                                                     ->get_top_level_node();
00642                                 if (pk_top == bi) {
00643                                     found = true;
00644                                     break;
00645                                 }
00646                             }
00647 
00648                             if (!found) {
00649 
00650                                 cerr << "check_slow_consistency: node "
00651                                      << pert_node->format_label()
00652                                      << " (" << pert_node
00653                                      << ") on slow_perturbed list"
00654                                      << endl;
00655                                 cerr << "                        "
00656                                      << "of " << bi->format_label()
00657                                      << " is not perturbed by it"
00658                                      << endl;
00659 
00660                                 pert_node->print_perturber_list();
00661 
00662                             } else {
00663 
00664                                 // Check kappa.
00665 
00666                                 real pk = pert_node->get_oldest_daughter()
00667                                                    ->get_kappa();
00668 
00669                                 if (pk != s->get_kappa()) {
00670                                     cerr << "check_slow_consistency: node "
00671                                          << pert_node->format_label()
00672                                          << " on slow_perturbed list of ";
00673                                     cerr << bi->format_label()
00674                                          << " has kappa = " << pk
00675                                          << " != " << s->get_kappa()
00676                                          << endl;
00677                                 }
00678                             }
00679                         }
00680                     }
00681 
00682                     s = s->get_next();
00683 
00684                 }
00685             }
00686         }
00687     }
00688 
00689     // Check consistency in the reverse direction.
00690 
00691     for_all_leaves(hdyn, b, bi) {
00692         if (bi->is_low_level_node()
00693             && bi->get_elder_sister() == NULL
00694             && bi->get_slow()) {
00695 
00696             hdyn *pnode = bi->find_perturber_node();
00697             hdyn *par = bi->get_parent();
00698 
00699             if (!pnode || !pnode->get_valid_perturbers()) {
00700 
00701                 cerr << "check_slow_consistency: "
00702                      << "no valid perturber node for slow binary "
00703                      << par->format_label() << endl;
00704 
00705             } else {
00706 
00707                 if (par->is_top_level_node()) {
00708 
00709                     for (int k = 0; k < pnode->get_n_perturbers(); k++) {
00710 
00711                         hdyn *pert_top = pnode->get_perturber_list()[k]
00712                                               ->get_top_level_node();
00713 
00714                         if (pert_top != par) {  // redundant, now...
00715 
00716                             // Perturbers not in this clump should have
00717                             // slow_perturbed top-level data.
00718 
00719                             bool found = false;
00720                             slow_perturbed *s = pert_top->get_sp();
00721 
00722                             while (s) {
00723                                 if (s->get_node() == par) found = true;
00724                                 s = s->get_next();
00725                             }
00726                             if (!found) {
00727 
00728                                 cerr << "check_slow_consistency: "
00729                                      << "no reference to slow binary CM "
00730                                      << par->format_label() << endl;
00731                                 cerr << "                        "
00732                                      << "on slow_perturbed list of perturber "
00733                                      << pert_top->format_label()
00734                                      << endl;
00735                                 cerr << "                        "
00736                                      << "at time " << b->get_system_time()
00737                                      << endl;
00738 
00739                                 bi->print_pert();               // component MF
00740                                 par->print_perturber_list();    // CM MF!
00741 
00742                                 pert_top->print_slow_perturbed();
00743                             }
00744                         }
00745                     }
00746                 }
00747             }
00748         }
00749     }
00750 }

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