Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

makesecondary.C

Go to the documentation of this file.
00001 
00029 
00030 //                 Steve McMillan, July 1996
00031 //                 Simon Portegies Zwart, Tokyo, December 1997
00032 
00033 #include "node.h"
00034 
00035 #define  SEED_STRING_LENGTH  256
00036 char  tmp_string[SEED_STRING_LENGTH];
00037 
00038 #ifdef TOOLBOX
00039 
00040 local void name_from_components(node *od, node *yd)
00041 {
00042     char name1[256], name[256];
00043     strcpy(name1, od->format_label());
00044     sprintf(name, "(%s,%s)", name1, yd->format_label());
00045     od->get_parent()->set_name(name);
00046     od->get_parent()->set_index(-1);
00047 }
00048 
00049 // add_secondary: Add a secondary component to a primary to make
00050 //                a binary.  Only the mass, name and tree structure
00051 //                are modified at this stage.
00052 //
00053 //                The old default naming was for primary and secondary
00054 //                components to have names "na" and "nb", respectively,
00055 //                where "n" was the name of the original star.  However,
00056 //                this leads to unique_id problems with worldlines, so
00057 //                numeric names are now the default, with (a,b) the
00058 //                alternative.  (Steve, 5/01)
00059 
00060 local real add_secondary(node* original, real mass_ratio,
00061                          bool force_index, int &nmax,
00062                          bool split)
00063 {
00064     node* primary = new node;
00065     node* secondary = new node;
00066 
00067     // Add new links.
00068 
00069     original->set_oldest_daughter(primary);
00070 
00071     primary->set_parent(original);
00072     secondary->set_parent(original);
00073 
00074     primary->set_younger_sister(secondary);
00075     secondary->set_elder_sister(primary);
00076 
00077     // Set new masses.
00078 
00079     if(!split) {
00080         primary->set_mass(original->get_mass());
00081         secondary->set_mass(mass_ratio*original->get_mass());
00082         original->inc_mass(secondary->get_mass());
00083     }
00084     else {
00085         real m_total = original->get_mass();
00086         real m_prim = m_total / (1+mass_ratio);
00087         real m_sec = m_total - m_prim;
00088         if(m_prim<m_sec) {
00089             real tmp = m_sec;
00090             m_sec = m_prim;
00091             m_prim = tmp;
00092         }
00093 
00094         primary->set_mass(m_prim);
00095         secondary->set_mass(m_sec);
00096     }
00097 
00098     // There are two possible naming conventions.  If force_index is
00099     // false, then we take the original name and add "a" and "b" for
00100     // the component names.  If force_index is true, the first component
00101     // inherits the original index and the second component gets an
00102     // index offset by some "resonable" amount.  In either case, the new
00103     // CM name is (cpt1,cpt1), as usual.
00104 
00105     if (force_index) {
00106 
00107         primary->set_index(original->get_index());
00108         secondary->set_index(original->get_index()+nmax);
00109 
00110     } else {
00111 
00112         if (original->get_name() == NULL) {
00113 
00114             // Make a name for use by the components.
00115 
00116             char tmp[128];
00117             if (original->get_index() >= 0)
00118                 sprintf(tmp, "%d", original->get_index());
00119             else
00120                 sprintf(tmp, "X");
00121             original->set_name(tmp);
00122         }
00123 
00124         if (original->get_name() != NULL) {
00125 
00126             // Label components "a" and "b".
00127 
00128             primary->set_name(original->get_name());
00129             secondary->set_name(original->get_name());
00130             strcat(primary->get_name(), "a");
00131             strcat(secondary->get_name(), "b");
00132         }
00133     }
00134 
00135     // Make standard CM name.
00136 
00137     name_from_components(primary, secondary);
00138 
00139     return secondary->get_mass();
00140 }
00141 
00142 local void warning(real mmin, real lower_limit) {
00143 
00144   cerr << "WARNING:" << endl;
00145   cerr << "       local void makesecondary(node*, real, real, bool)" << endl;
00146   cerr << "       actual minimum mass " << mmin
00147        << " is larger than lower limit " << lower_limit << ";" << endl;
00148   cerr << "       continuing execution with true minimum mass" << endl;
00149 
00150 }
00151 
00152 local real random_mass_ratio(const real qmin, 
00153                              const real qmax) {
00154 
00155   // For now, equal probability in q between qmin and qmax.
00156 
00157   return randinter(qmin, qmax);
00158 }
00159 
00160 local void name_recursive(node *b)
00161 {
00162     // Make a standard CM name, making sure that we build names
00163     // from the bottom up.
00164 
00165     node *od = b->get_oldest_daughter();
00166     if (od) {
00167         node *yd = od->get_younger_sister();
00168         name_recursive(od);
00169         name_recursive(yd);
00170         name_from_components(od, yd);
00171     }
00172 }
00173 
00174 local int check_indices(node *b)
00175 {
00176     int nmax = 0;
00177     bool all_ok = true;
00178 
00179     for_all_leaves(node, b, bb) {
00180 
00181         bb->set_name(NULL);
00182 
00183         if (bb->get_index() >= 0)
00184             nmax = max(nmax, bb->get_index());
00185         else
00186             all_ok = false;
00187     }
00188 
00189     if (!all_ok) {
00190 
00191         cerr << "    makesecondary: assigning numeric indices to nodes" << endl;
00192 
00193         for_all_leaves(node, b, bb) {
00194             if (bb->get_index() <= 0)
00195                 bb->set_index(++nmax);
00196         }
00197     }
00198 
00199     // Redetermine all center-of-mass names.
00200 
00201     for_all_nodes(node, b, bb)
00202         if (bb!= b && bb->is_parent())
00203             name_recursive(bb);
00204 
00205     return nmax;
00206 }
00207 
00208 local void makesecondary(node* b, real binary_fraction,
00209                        real min_mprim, real max_mprim,
00210                        real lower_limit, real upper_limit, 
00211                        bool force_index, bool q_flag, bool ignore_limits,
00212                        bool split)
00213 {
00214     PRI(4); PRL(binary_fraction);
00215     PRI(4); PRL(min_mprim);
00216     PRI(4); PRL(max_mprim);
00217     PRI(4); PRL(q_flag);
00218     PRI(4); PRL(lower_limit);
00219     PRI(4); PRL(upper_limit);
00220     PRI(4); PRL(ignore_limits);
00221     PRI(4); PRL(split);
00222 
00223     int nmax = 0;
00224     if (force_index) {
00225 
00226         // All stars will are to have numeric labels.  First check
00227         // that the original labels are numeric.  If not, force all
00228         // labels into numeric form.  Function check_indices() returns
00229         // the maximum (corrected) index found.
00230 
00231         nmax = check_indices(b);
00232 
00233         // Round nmax up to something "reasonable".
00234 
00235         nmax = (int)(pow(10., ((int)log10((real)nmax)) + 1.0) + 0.1);
00236     }
00237 
00238     // For now, use a flat distribution in secondary mass ratio.
00239     // Assume that the probability of a star being the primary of
00240     // a binary is independent of mass.
00241 
00242     real sum = 0;
00243     b->set_mass(0);
00244 
00245     real m_prim, q;
00246     real m_primaries=0, m_secondaries=0, m_total=0;
00247 
00248     if (q_flag) {
00249 
00250         // Choose the secondary mass ratio uniformly on
00251         // [lower_limit, upper_limit].
00252 
00253         for_all_daughters(node, b, bi) {
00254             if(!bi->is_parent()) {
00255 
00256                 m_prim = bi->get_mass();
00257                 m_primaries += m_prim;
00258 
00259                 if (m_prim >= min_mprim && m_prim <= max_mprim) {
00260                     sum += binary_fraction;
00261                     if (sum >= 0.9999999999) {  // avoid roundoff problems!
00262                         sum = 0;
00263                         q = random_mass_ratio(lower_limit, upper_limit);
00264                         
00265                         m_secondaries += add_secondary(bi, q, force_index, nmax, split);
00266                     }
00267                 }
00268             }
00269         }
00270 
00271     } else {
00272 
00273         // Secondary mass ratio chosen uniformly on [mmin, mmax],
00274         // where mmin and mmax are the lower and upper limits
00275         // specified  on the command line.
00276 
00277         real mmin = VERY_LARGE_NUMBER, mmax = 0, qmin = 0, qmax;
00278 
00279         if (ignore_limits) {
00280 
00281             mmin = lower_limit;
00282             mmax = upper_limit;
00283 
00284         } else {
00285 
00286             for_all_daughters(node, b, bi) {
00287                 if (bi->is_leaf()) {
00288                     mmin = min(mmin, bi->get_mass());
00289                     mmax = max(mmax, bi->get_mass());
00290                 }
00291             }
00292 
00293             if (mmin < lower_limit) {
00294                 warning(mmin, lower_limit);
00295                 sprintf(tmp_string,
00296                         "         -l = %5.4f adopted", mmin); 
00297                 b->log_comment(tmp_string);
00298             }
00299 
00300             if (mmax > upper_limit) {
00301                 warning(mmax, upper_limit);
00302                 sprintf(tmp_string,
00303                         "         -u = %5.4f adopted", mmax); 
00304                 b->log_comment(tmp_string);
00305             }
00306         }
00307             
00308         // Note that the following loop is essentially the same code as above.
00309 
00310         for_all_daughters(node, b, bi) {
00311             if(!bi->is_parent()) {
00312 
00313                 m_prim = bi->get_mass();
00314                 m_primaries += m_prim;
00315 
00316                 if (m_prim >= min_mprim && m_prim <= max_mprim) {
00317                     sum += binary_fraction;
00318                     if (sum >= 0.9999999999) {  // avoid roundoff problems!
00319                         sum = 0;
00320                         qmin = mmin/bi->get_mass();
00321                         qmax = min(mmax, bi->get_mass())/bi->get_mass();
00322                         q = random_mass_ratio(qmin, qmax);
00323                         m_secondaries += add_secondary(bi, q, force_index, nmax, split);
00324                     }
00325                 }
00326             }
00327         }
00328     }
00329 
00330     real m_tot = m_primaries + m_secondaries;
00331     if(split) {
00332         m_tot = m_primaries;
00333         m_primaries -= m_secondaries;
00334     }
00335     b->set_mass(m_tot); 
00336     real old_mtot = b->get_starbase()->conv_m_dyn_to_star(1);
00337 
00338     if(old_mtot>0 && old_mtot<m_tot) {
00339         real old_r_vir= b->get_starbase()->conv_r_star_to_dyn(1);
00340         real old_t_vir= b->get_starbase()->conv_t_star_to_dyn(1);
00341         b->get_starbase()->set_stellar_evolution_scaling(m_tot,
00342                                                          old_r_vir,
00343                                                          old_t_vir);
00344     }
00345 
00346     if(split) {
00347         sprintf(tmp_string,
00348                 "       total mass in primaries = %8.2f Solar", m_primaries); 
00349         b->log_comment(tmp_string);
00350     }
00351 
00352     sprintf(tmp_string,
00353             "       total mass in secondaries = %8.2f Solar", m_secondaries); 
00354     b->log_comment(tmp_string);
00355 
00356     // Update mass info, if any.
00357 
00358     if (find_qmatch(b->get_log_story(), "initial_mass"))
00359         putrq(b->get_log_story(), "initial_mass", m_tot);
00360 }
00361 
00362 void main(int argc, char ** argv)
00363 {
00364 
00365     bool split = false;
00366     bool ignore_limits = false;
00367     real binary_fraction = 0.1;
00368     real lower_limit = 0.0;
00369     bool u_flag = false;
00370     real upper_limit = VERY_LARGE_NUMBER;
00371     real max_mprim = VERY_LARGE_NUMBER;
00372     real min_mprim = 0;
00373     bool force_index = true;
00374     real q_flag = false;             // flag for mass-ratio selection
00375     int random_seed = 0;
00376     char seedlog[64];
00377 
00378     check_help();
00379 
00380     extern char *poptarg;
00381     int c;
00382     char* param_string = "qf:M:m:il:nu:Ss:I";
00383 
00384     while ((c = pgetopt(argc, argv, param_string)) != -1)
00385         switch(c) {
00386 
00387             case 'f': binary_fraction = atof(poptarg);
00388                       break;
00389             case 'i': force_index = true;
00390                       break;
00391             case 'I': ignore_limits = true;
00392                       break;
00393             case 'l': lower_limit = atof(poptarg);
00394                       break;
00395             case 'M': max_mprim = atof(poptarg);
00396                       break;
00397             case 'm': min_mprim = atof(poptarg);
00398                       break;
00399             case 'q': q_flag = true;
00400                       break;
00401             case 'S': split = true;
00402                       break;
00403             case 's': random_seed = atoi(poptarg);
00404                       break;
00405             case 'u': upper_limit = atof(poptarg);
00406                       u_flag = true;
00407                       break;
00408             case '?': params_to_usage(cerr, argv[0], param_string);
00409                       exit(1);
00410         }
00411 
00412     if (!u_flag && q_flag) upper_limit = 1;
00413 
00414     if (binary_fraction < 0 || binary_fraction > 1)
00415         err_exit("makesecondary: Illegal binary fraction");
00416     if (q_flag && lower_limit > 1)
00417         err_exit("makesecondary: Illegal minimum mass for secondary");
00418     if (q_flag && lower_limit < 0) {
00419         cerr << "Negative mass ratio not allowed; use -l 0" << endl;
00420         lower_limit = 0;
00421     }
00422     if (q_flag && upper_limit > 1) {
00423         cerr << "Maximum mass ratio > 1 not allowed; use -u 1" << endl;
00424         upper_limit = 1;
00425     }
00426 
00427     if (lower_limit < 0)
00428         err_exit("Invalid lower limit");
00429 
00430     if (upper_limit < 0)
00431         err_exit("Invalid upper limit");
00432     else if (lower_limit > upper_limit)
00433         err_exit("Invalid selection of upper and lower limits to mass-ratio");
00434 
00435     if (max_mprim < min_mprim)
00436         err_exit("Invalid upper and lower primary mass selections");
00437 
00438     node* b;
00439     b = get_node(cin);
00440 
00441     b->log_history(argc, argv);
00442 
00443     int actual_seed = srandinter(random_seed);
00444 
00445     sprintf(seedlog, "       random number generator seed = %d", actual_seed);
00446     b->log_comment(seedlog);
00447 
00448     makesecondary(b, binary_fraction, min_mprim, max_mprim, 
00449                 lower_limit, upper_limit, force_index, q_flag,
00450                 ignore_limits, split);
00451 
00452     put_node(cout, *b);
00453     rmtree(b);
00454 }
00455 #endif

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