Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

hdyn_inline.C

Go to the documentation of this file.
00001 
00002        //=======================================================//    _\|/_
00003       //  __  _____           ___                    ___       //      /|\ ~
00004      //  /      |      ^     |   \  |         ^     |   \     //          _\|/_
00005     //   \__    |     / \    |___/  |        / \    |___/    //            /|\ ~
00006    //       \   |    /___\   |  \   |       /___\   |   \   // _\|/_
00007   //     ___/   |   /     \  |   \  |____  /     \  |___/  //   /|\ ~
00008  //                                                       //            _\|/_
00009 //=======================================================//              /|\ ~
00010 
00011 // hdyn_inline.C:  Inline functions for use in hdyn_ev.C, hdyn_grape4/6.C,
00012 //                 and hdyn_slow.C.
00013 //
00014 //                 Include this file directly into the source files,
00015 //                 rather than placing these functions in libraries.
00016 //
00017 // Local inline functions defined:
00018 //
00019 //      void update_nn_coll
00020 //      real define_perturbation_radius_factor
00021 //      bool is_perturber
00022 //      real binary_scale
00023 //
00024 //----------------------------------------------------------------------
00025 
00026 // inline void update_nn_coll
00027 //      update various neighbor pointers associated with a node.
00028 
00029 local inline void update_nn_coll(hdyn *this_node, int id,
00030                                  real d_to_b_sq, hdyn *b,
00031                                  real &d_nn_sq, hdyn *&nn,
00032                                  real sum_of_radii,
00033                                  real &d_coll_sq, hdyn *&coll)
00034 
00035 // Note: arguments "this_node" and "id" are needed only for possible
00036 //       diagnostic output.
00037 
00038 {
00039     if (d_to_b_sq < d_nn_sq) {
00040 
00041 #if 0
00042         hdyn *old_nn = nn;
00043         real old_d_nn_sq = d_nn_sq;
00044 #endif
00045 
00046         d_nn_sq = d_to_b_sq;
00047         nn = b;
00048 
00049 #if 0
00050         if (this_node->get_real_system_time() > 13.62265) {
00051             cerr << "update_nn_coll(" << id << "): ";
00052             PRL(this_node->format_label());
00053             PRI(4); PRC(old_nn); PRL(sqrt(old_d_nn_sq));
00054             if (old_d_nn_sq < 0.5*VERY_LARGE_NUMBER) {
00055                 PRI(4); cerr << "old: " << flush;
00056                 if (old_nn->is_valid()) {
00057                     PRC(old_nn->format_label());
00058                 }
00059                 if (old_d_nn_sq > 0) {
00060                     PRC(sqrt(old_d_nn_sq));
00061                 }
00062                 cerr << endl << flush;
00063             }
00064             PRI(4); PRC(nn->format_label()); PRL(sqrt(d_nn_sq));
00065         }
00066 #endif
00067 
00068     }
00069 
00070     real coll_dist = d_to_b_sq - sum_of_radii*sum_of_radii;
00071 
00072     if (coll_dist < d_coll_sq) {
00073         d_coll_sq = coll_dist;
00074         coll = b;
00075     }
00076 }
00077 
00078 
00079 // Set/check criteria for placing bi on the perturber list of a node.
00080 // Note that these functions are the *only* places in kira where this
00081 // criterion is defined.
00082 
00083 #define PERTURBER_CRITERION     2       // For determination of perturbers
00084                                         //   0:  distance only
00085                                         //   1:  perturbation (includes mass)
00086                                         //   2:  hybrid
00087 
00088 // inline real define_perturbation_radius_factor()
00089 // inline bool is_perturber()
00090 
00091 // Simple distance criterion for placing bi on perturber list is
00092 //
00093 //          distance_squared  <  perturbation_radius^2
00094 //
00095 // where
00096 //
00097 //          perturbation_radius  =  gamma^{-1/3} * r_bin
00098 //
00099 // and
00100 //
00101 //          r_bin  =  max(a, rij).
00102 //
00103 // (Note: we used to have r_bin  =  min(d_min, max(a, rij)), which is OK if
00104 //  rij is never greater than d_min, but this may not always be the case.)
00105 //
00106 // This is OK for roughly equal-mass binaries, but it doesn't take
00107 // masses into account -- IMPORTANT when a wide mass range exists.
00108 // (Also, it is not clear that d_min is the correct upper limit on
00109 // the "size" of the binary r_bin.)
00110 //
00111 // The criterion including masses, which reduces to the above criterion
00112 // for equal masses, is
00113 //
00114 //            2 * m_pert * r_bin               M_bin
00115 //          ---------------------  =  gamma * -------
00116 //          perturbation_radius^3             r_bin^2
00117 //
00118 // or
00119 //
00120 //          perturbation_radius  =  gamma^{-1/3} * r_bin
00121 //                                      * (2 * m_pert / M_bin)^{1/3}.
00122 //
00123 // Note that, in the "perturbation" definitions, we work with cubed radii
00124 // (to avoid cube roots in the loop that computes the perturber list).
00125 // In these cases, "perturbation_radius_factor" is (apart from the mass
00126 // factor) perturbation_radius^3.
00127 //
00128 // Also,in these cases, pert_factor_sq is really gamma2^{-1/3} = gamma^{-2/3}.
00129 // All we really need is 1/gamma!  FIX THIS SOON!!
00130 //
00131 //*** Distance criterion is fine for perturbers of mass comparable to or
00132 //*** less than the masses of the binary components.
00133 //*** Hybrid criterion uses a fixed perturber radius, but then also includes
00134 //*** more distant massive stars.
00135 
00136 // binary_scale:  compute an appropriate "size" for a binary.
00137 
00138 local real binary_scale(hdyn* cm)
00139 {
00140     static hdyn *last_cm = NULL;
00141     static xreal last_time = 0;
00142     static real last_scale = 0;
00143 
00144     xreal time = cm->get_time();
00145 
00146     if (cm == last_cm
00147         && time == last_time)
00148         return last_scale;
00149 
00150     hdyn *d1 = cm->get_oldest_daughter();
00151     if (!d1) return 0;
00152 
00153     hdyn *d2 = d1->get_younger_sister();
00154     if (!d2) return 0;
00155 
00156     real sep = abs(d1->get_pos() - d2->get_pos());
00157     real energy = 0.5 * square(d1->get_vel() - d2->get_vel())
00158                         - cm->get_mass() / sep;
00159     real sma = 0.5 * cm->get_mass() / abs(energy);
00160 
00161     last_cm = cm;
00162     last_time = time;
00163     last_scale = max(sma, sep);
00164 
00165     //  =  max(2*sma, sep);     // Better? -- more conservative, and also
00166                                 // avoids discontinuous changes in perturber
00167                                 // lists as the binary phase changes.
00168                                 // -- changes default gamma.
00169     return last_scale;
00170 }
00171 
00172 // define_perturbation_radius_factor:
00173 //               define the value of perturber_radius_squared.
00174 
00175 local inline real define_perturbation_radius_factor(hdyn *b,    // 'this' node
00176                                                     real pert_factor_sq)
00177 {
00178     int  perturber_criterion = b->get_kira_options()->perturber_criterion;
00179     // real d_min_sq = b->get_d_min_sq();
00180     real r_bin = binary_scale(b);
00181     real m_bin = b->get_mass();
00182 
00183     // Note that pert_factor_sq will be gamma23 in normal use, but
00184     // it may in general take any value.
00185 
00186     // NOTE: removed "min(d_min_sq..." lines (Steve, 12/01).
00187 
00188     if (perturber_criterion == 0) {
00189 
00190         // Distance criterion:
00191 
00192         // return pert_factor_sq * min(d_min_sq, r_bin * r_bin);
00193         return pert_factor_sq * r_bin * r_bin;
00194 
00195     } else if (perturber_criterion == 1) {
00196 
00197 
00198         // real rp2 = pert_factor_sq * min(d_min_sq, r_bin * r_bin);
00199         real rp2 = pert_factor_sq * r_bin * r_bin;
00200 
00201         // return 2 * pow(rp2, 1.5) / m_bin;
00202         return 2 * rp2 * sqrt(rp2) / m_bin;
00203 
00204     } else if (perturber_criterion == 2) {
00205 
00206         // Hybrid criterion for perturbation radius is the distance
00207         // criterion, but storing rp^3 instead of rp^2; alternatively,
00208         // it is the perturbation criterion without the mass factor:
00209 
00210         // real rp2 = pert_factor_sq * min(d_min_sq, r_bin * r_bin);
00211         real rp2 = pert_factor_sq * r_bin * r_bin;
00212 
00213         // return pow(rp2, 1.5);
00214         return rp2 * sqrt(rp2);
00215     }
00216 }
00217 
00218 // perturbation_scale_sq: return a characteristic squared scale for the
00219 //                        radius of b's perturber sphere (Steve, 12/01)
00220 
00221 local inline real perturbation_scale_sq(hdyn *b,
00222                                         real pert_factor_sq)
00223 {
00224     // Decode the perturber criterion and return the radius that would
00225     // be applied for a perturber of mass equal to half the mass of b.
00226     // Basically, we just repeat the action of the previous function,
00227     // but return rp2.  Keep the function here so we can maintain
00228     // consistency if the criteria change.  The pert_factor_sq used
00229     // here must be the same as that sent to the previous function.
00230     //
00231     // Note that we end up calling binary_scale TWICE -- once in the
00232     // previous function, and again here.  To be fixed...
00233 
00234     if (!b->get_oldest_daughter()) return 0;
00235 
00236     real r_bin = binary_scale(b);
00237     return pert_factor_sq * r_bin * r_bin;
00238 }
00239 
00240 // is_perturber: check the perturbation criterion.
00241 
00242 local inline bool is_perturber(hdyn *b,                      // 'this' node
00243                                real m_pert,                  // perturber mass
00244                                real distance_squared,
00245                                real perturbation_radius_factor)
00246 {
00247     int  perturber_criterion = b->get_kira_options()->perturber_criterion;
00248     real m_bin = b->get_mass();
00249 
00250     if (perturber_criterion == 0) {
00251 
00252         // Distance criterion:
00253 
00254         return (distance_squared < perturbation_radius_factor);
00255 
00256     } else if (perturber_criterion == 1) {
00257 
00258         // Perturbation criterion:
00259 
00260         return (distance_squared * sqrt(distance_squared)
00261                                         < m_pert * perturbation_radius_factor);
00262 
00263     } else if (perturber_criterion == 2) {
00264 
00265         // Hybrid criterion is distance criterion, plus additional
00266         // massive perturbers:
00267 
00268         real d3 = distance_squared * sqrt(distance_squared);
00269 
00270         if (m_pert <= 0.5*m_bin)
00271             return (d3 < perturbation_radius_factor);           // low-mass
00272 
00273         return (0.5*m_bin*d3                                    // high-mass
00274                      < m_pert * perturbation_radius_factor);
00275 
00276     }
00277 }
00278 
00279 // crit_separation_cubed: return the critical separation for the
00280 //                        adopted perturbation criterion.
00281 
00282 local inline real crit_separation_cubed(hdyn *b,        // binary CM node
00283                                         real m_pert,    // perturber mass
00284                                         real r_bin,     // binary scale
00285                                         real gamma)     // perturbation
00286 {
00287     real m_bin = b->get_mass();
00288     real d_min_sq = b->get_d_min_sq();
00289     int  perturber_criterion = b->get_kira_options()->perturber_criterion;
00290 
00291     real d2 = min(d_min_sq, r_bin * r_bin);
00292     real d3 = d2 * sqrt(d2) / gamma;
00293 
00294     if (perturber_criterion == 0
00295         || (perturber_criterion == 2 && m_pert <= 0.5 * m_bin))
00296 
00297         return d3;
00298 
00299     else
00300 
00301         return 2 * (m_pert / m_bin) * d3;
00302 }
00303 
00304 local inline real time_to_radius(real dr,       // distance to cover
00305                                  real vr,       // relative radial velocity
00306                                  real ar)       // relative radial acceleration
00307 {
00308     // Estimate the time required for two particles, of given relative
00309     // velocity and acceleration, to decrease their separation by dr.
00310     // Use the following time scales:
00311     //
00312     //          t1  =  dr / |vr|                ("crossing" time)
00313     //          t2  =  sqrt (2 * dr / |ar|)     ("free-fall" time)
00314     //
00315     // If the particles are in the same clump, then ar is the two-body
00316     // acceleration and t2 really is the free-fall time.  Otherwise,
00317     // ar is the relative acceleration in the global cluster field.
00318 
00319     if (dr <= 0) return 0;
00320 
00321     real dt = VERY_LARGE_NUMBER;
00322 
00323     if (vr < 0) dt = -dr / vr;
00324     if (ar < 0) dt = min(dt, sqrt (-2 * dr / ar));
00325 
00326     return dt;
00327 }

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