00001
00029
00030
00031
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
00050
00051
00052
00053
00054
00055
00056
00057
00058
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
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
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
00099
00100
00101
00102
00103
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
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
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
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
00156
00157 return randinter(qmin, qmax);
00158 }
00159
00160 local void name_recursive(node *b)
00161 {
00162
00163
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
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
00227
00228
00229
00230
00231 nmax = check_indices(b);
00232
00233
00234
00235 nmax = (int)(pow(10., ((int)log10((real)nmax)) + 1.0) + 0.1);
00236 }
00237
00238
00239
00240
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
00251
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) {
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
00274
00275
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
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) {
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
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;
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