00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 #include "node.h"
00077 #include "double_star.h"
00078 #include "main_sequence.h"
00079
00080 #ifndef TOOLBOX
00081
00082 #define REPORT_ADD_DOUBLE false
00083 #define REPORT_DEL_DOUBLE false
00084 #define REPORT_EVOLVE_DOUBLE false
00085
00086 #define SEED_STRING_LENGTH 255
00087
00088 void add_secondary(node* original, real mass_ratio) {
00089
00090 node* primary = new node;
00091 node* secondary = new node;
00092
00093
00094
00095 original->set_oldest_daughter(primary);
00096
00097 primary->set_parent(original);
00098 secondary->set_parent(original);
00099
00100 primary->set_younger_sister(secondary);
00101 secondary->set_elder_sister(primary);
00102
00103
00104
00105 primary->set_mass(original->get_mass());
00106 secondary->set_mass(mass_ratio*original->get_mass());
00107 original->inc_mass(secondary->get_mass());
00108
00109
00110
00111 if (original->get_name() == NULL)
00112 if (original->get_index() >= 0) {
00113 char tmp[64];
00114 sprintf(tmp, "%d", original->get_index());
00115 original->set_name(tmp);
00116 }
00117
00118 primary->set_name(original->get_name());
00119 secondary->set_name(original->get_name());
00120 strcat(primary->get_name(), "a");
00121 strcat(secondary->get_name(), "b");
00122
00123 }
00124
00125 void mksecondary(node* b, real binary_fraction, real lower_limit) {
00126
00127
00128
00129
00130
00131 real sum = 0;
00132 b->set_mass(0);
00133
00134 for_all_daughters(node, b, bi) {
00135 sum += binary_fraction;
00136 if (sum >= 1) {
00137 sum -= 1;
00138
00139 real mass_ratio = randinter(lower_limit, 1);
00140 add_secondary(bi, mass_ratio);
00141
00142 }
00143 b->inc_mass(bi->get_mass());
00144 }
00145 }
00146
00147 #if 0
00148 real random_exponential_mass(const real m_min,
00149 const real m_max,
00150 const real m_alpha) {
00151
00152 real random = randinter(0., 1.);
00153 real m_const = pow(m_min, 1-m_alpha)
00154 - pow(m_max, 1-m_alpha);
00155 real m_prim = pow(random*m_const
00156 + pow(m_max, 1-m_alpha), 1/(1-m_alpha));
00157
00158 return m_prim;
00159 }
00160 #endif
00161
00162
00163 char* type_string(mass_ratio_distribution qf) {
00164
00165 local char qf_name[SEED_STRING_LENGTH];
00166 switch(qf) {
00167 case Equal_q:
00168 sprintf(qf_name, "Equal_q");
00169 break;
00170 case Flat_q:
00171 sprintf(qf_name, "Flat_q");
00172 break;
00173 case qf_Power_Law:
00174 sprintf(qf_name, "Power_Law");
00175 break;
00176 case Thermal_Distribution:
00177 sprintf(qf_name, "Hogeveen");
00178 break;
00179 default:
00180 sprintf(qf_name, "Unknown_qf");
00181 break;
00182 }
00183 return qf_name;
00184 }
00185
00186 mass_ratio_distribution extract_mass_ratio_distribution_type_string(char* type_string) {
00187
00188 mass_ratio_distribution type = Unknown_qf;
00189
00190 if (!strcmp(type_string, "Equal_q"))
00191 type = Equal_q;
00192 else if (!strcmp(type_string, "Unknown_qf"))
00193 type = Unknown_qf;
00194 else if (!strcmp(type_string, "Flat_q"))
00195 type = Flat_q;
00196 else if (!strcmp(type_string, "Power_Law"))
00197 type = qf_Power_Law;
00198 else if (!strcmp(type_string, "Hogeveen"))
00199 type = Hogeveen;
00200 else {
00201 cerr << " in extract_eccentricity_type_string." << endl;
00202 err_exit("No proper mass-ratio distribution indicated");
00203
00204 }
00205
00206 return type;
00207 }
00208
00209
00210 local real qf_Hogeveen(real q_lower, real q_upper) {
00211
00212 real q;
00213 do {
00214 q = 1./pow(randinter(0.125, 1.), 1/3.) - 1;
00215 }
00216 while(q<q_lower || q>=q_upper);
00217
00218 return q;
00219 }
00220
00221 real get_random_mass_ratio(real q_lower, real q_upper,
00222 mass_ratio_distribution qf,
00223 real exponent) {
00224 real q;
00225 switch(qf) {
00226 case Equal_q:
00227 if (q_lower==0) {
00228 cerr << "get_random_mass_ratio:"<<endl;
00229 cerr << "unambiguous choise of Equal_q."<<endl;
00230 cerr << "Use -q option to set fixed mass ratio."<<endl;
00231 exit(1);
00232 }
00233 q = q_lower;
00234 break;
00235 case Flat_q:
00236 q = randinter(q_lower, q_upper);
00237 break;
00238 case qf_Power_Law:
00239 q = general_power_law(q_lower, q_upper, exponent);
00240 break;
00241 case Hogeveen:
00242 q = qf_Hogeveen(q_lower, q_upper);
00243 break;
00244 default:
00245 cerr << "WARNING: \n"
00246 << " real get_random_mass_ratio:\n"
00247 << " parameters not properly defined.\n";
00248 exit(1);
00249 }
00250
00251 return q;
00252 }
00253
00254 char* type_string(sma_distribution smaf) {
00255
00256 local char smaf_name[SEED_STRING_LENGTH];
00257 switch(smaf) {
00258 case Equal_sma:
00259 sprintf(smaf_name, "Equal_sma");
00260 break;
00261 case sma_Power_Law:
00262 sprintf(smaf_name, "Power_Law");
00263 break;
00264 case Duquennoy_Mayor:
00265 sprintf(smaf_name, "Duquennoy_Mayor");
00266 break;
00267 case Eggleton:
00268 sprintf(smaf_name, "Eggleton");
00269 break;
00270 default:
00271 sprintf(smaf_name, "Unknown_smaf");
00272 break;
00273 }
00274 return smaf_name;
00275 }
00276
00277 sma_distribution
00278 extract_semimajor_axis_distribution_type_string(char* type_string) {
00279
00280 sma_distribution type = Unknown_smaf;
00281
00282 if (!strcmp(type_string, "Equal_sma"))
00283 type = Equal_sma;
00284 else if (!strcmp(type_string, "Duquennoy_Mayor"))
00285 type = Duquennoy_Mayor;
00286 else if (!strcmp(type_string, "Eggleton"))
00287 type = Eggleton;
00288 else if (!strcmp(type_string, "Unknown_smaf"))
00289 type = Unknown_smaf;
00290 else if (!strcmp(type_string, "Power_Law"))
00291 type = sma_Power_Law;
00292 else {
00293 cerr << "No proper semimajor axis distribution indicated"
00294 << " in extract_semimajor_axis_type_string." << endl;
00295 exit(1);
00296 }
00297
00298 return type;
00299 }
00300
00301
00302 local real smaf_Duquenoy_Mayor(real a_lower, real a_upper,
00303 real total_mass) {
00304
00305 real lp_mean = 4.8;
00306 real lp_sigma = 2.3;
00307 real lp, sma;
00308 do {
00309 lp = lp_mean + lp_sigma*gauss();
00310 real a_tmp = pow(pow(10., lp)*cnsts.physics(seconds_per_day), 2)
00311 * (cnsts.physics(G)*cnsts.parameters(solar_mass)*
00312 total_mass)/4*pow(cnsts.mathematics(pi), 2);
00313 sma = pow(a_tmp, 1./3.)/cnsts.parameters(solar_radius);
00314 }
00315 while(sma<a_lower || sma>=a_upper);
00316
00317 return sma;
00318 }
00319
00320
00321 local real smaf_Eggleton(real a_lower, real a_upper,
00322 real m_prim, real m_sec) {
00323
00324 real p_lower = semi_to_period(a_lower, m_prim, m_sec);
00325 real p_upper = semi_to_period(a_upper, m_prim, m_sec);
00326
00327
00328
00329 real mpf = pow(m_prim, 2.5)/5.e+4;
00330 real rnd_min = pow(p_upper * mpf, 1./3.3)
00331 / (1 + pow(p_upper * mpf, 1./3.3));
00332 real rnd_max = pow(p_lower * mpf, 1./3.3)
00333 / (1 + pow(p_lower * mpf, 1./3.3));
00334
00335 real rnd = randinter(rnd_min, rnd_max);
00336 real p = pow(rnd/(1-rnd), 3.3)/mpf;
00337
00338
00339
00340 real sma = period_to_semi(p, m_prim, m_sec);
00341
00342 return sma;
00343 }
00344
00345 real get_random_semimajor_axis(real a_lower, real a_upper,
00346 sma_distribution smaf,
00347 real exponent, real m_prim, real m_sec) {
00348 real a;
00349 switch(smaf) {
00350 case Equal_sma:
00351 if (a_lower!=a_upper) {
00352 cerr << "get_random_semimajor_axis:"<<endl;
00353 cerr << "unambiguous choise of Equal_sma."<<endl;
00354 exit(1);
00355 }
00356 a = a_lower;
00357 break;
00358 case sma_Power_Law:
00359 a = general_power_law(a_lower, a_upper, exponent);
00360 break;
00361 case Duquennoy_Mayor:
00362 a = smaf_Duquenoy_Mayor(a_lower, a_upper, m_prim+m_sec);
00363 break;
00364 case Eggleton:
00365 a = smaf_Eggleton(a_lower, a_upper, m_prim, m_sec);
00366 break;
00367 default:
00368 cerr << "WARNING: \n"
00369 << " real get_random_semi_major_axis:\n"
00370 << " parameters not properly defined.\n";
00371 exit(1);
00372 }
00373
00374 return a;
00375 }
00376
00377
00378 char* type_string(ecc_distribution eccf) {
00379
00380 local char eccf_name[SEED_STRING_LENGTH];
00381 switch(eccf) {
00382 case Equal_ecc:
00383 sprintf(eccf_name, "Equal_ecc");
00384 break;
00385 case ecc_Power_Law:
00386 sprintf(eccf_name, "Power_Law");
00387 break;
00388 case Thermal_Distribution:
00389 sprintf(eccf_name, "Thermal_Distribution");
00390 break;
00391 default:
00392 sprintf(eccf_name, "Unknown_eccf");
00393 break;
00394 }
00395 return eccf_name;
00396 }
00397
00398 ecc_distribution
00399 extract_eccentricity_distribution_type_string(char* type_string) {
00400
00401 ecc_distribution type = Unknown_eccf;
00402
00403 if (!strcmp(type_string, "Equal_ecc"))
00404 type = Equal_ecc;
00405 else if (!strcmp(type_string, "Unknown_eccf"))
00406 type = Unknown_eccf;
00407 else if (!strcmp(type_string, "Power_Law"))
00408 type = ecc_Power_Law;
00409 else {
00410 cerr << "No proper eccentricity distribution indicated"
00411 << " in extract_eccentricity_type_string." << endl;
00412 exit(1);
00413 }
00414
00415 return type;
00416 }
00417
00418 local real eccf_Thermal_Distribution(real e_lower, real e_upper) {
00419
00420 real ecc = sqrt(randinter(e_lower, e_upper));
00421 return ecc;
00422 }
00423
00424 real get_random_eccentricity(real e_lower, real e_upper,
00425 ecc_distribution eccf,
00426 real exponent) {
00427 real e;
00428 switch(eccf) {
00429 case Equal_sma:
00430 if (e_lower<0) {
00431 cerr << "get_random_eccentricity:"<<endl;
00432 cerr << "unambiguous choise of Equal_ecc."<<endl;
00433 cerr << "Use -e option to set fixed eccentricity."<<endl;
00434 exit(1);
00435 }
00436 e = e_lower;
00437 break;
00438 case ecc_Power_Law:
00439 if (e_lower<0) e_lower=0;
00440 e = general_power_law(e_lower, e_upper, exponent);
00441 break;
00442 case Thermal_Distribution:
00443 if (e_lower<0) e_lower=0;
00444 e = eccf_Thermal_Distribution(e_lower, e_upper);
00445 break;
00446 default:
00447 cerr << "WARNING: \n"
00448 << " real get_random_eccentricity:\n"
00449 << " parameters not properly defined.\n";
00450 exit(1);
00451 }
00452
00453 return e;
00454 }
00455
00456 local void determine_semi_major_axis_limits(real m_prim, real m_sec, real ecc,
00457 real &a_min, real &a_max) {
00458
00459 real r_prim = zero_age_main_sequnece_radius(m_prim);
00460 real r_sec = zero_age_main_sequnece_radius(m_sec);
00461
00462
00463 real a_prim=0, a_sec=0;
00464 if (a_min>0) {
00465 a_prim = roche_radius(a_min, m_prim, m_sec);
00466 a_sec = roche_radius(a_min, m_sec, m_prim);
00467 }
00468
00469
00470 a_min = max(a_min, max(a_prim, a_sec));
00471
00472 if (ecc>0)
00473 a_min = max(a_min, (r_prim+r_sec)/(1-ecc));
00474
00475 return;
00476 }
00477
00478 void mkrandom_binary( real m_min, real m_max,
00479 mass_function mf, real m_exp,
00480 real q_min, real q_max,
00481 mass_ratio_distribution qf, real q_exp,
00482 real a_min, real a_max,
00483 sma_distribution af, real a_exp,
00484 real e_min, real e_max,
00485 ecc_distribution ef, real e_exp,
00486 real &m_prim, real &m_sec, real &semi,
00487 real &ecc) {
00488
00489 m_prim = get_random_stellar_mass(m_min, m_max, mf, m_exp);
00490
00491
00492
00493
00494 if(q_min<=0)
00495 q_min = m_min/m_prim;
00496 real q = get_random_mass_ratio(q_min, q_max, qf, q_exp);
00497
00498 m_sec = q*m_prim;
00499
00500
00501
00502
00503
00504
00505
00506 real r_prim = zero_age_main_sequnece_radius(m_prim);
00507
00508 if(e_max>=1 && ef!=Equal_ecc)
00509 e_max = max(e_min, min(1., 1 - r_prim/a_max));
00510
00511 ecc = get_random_eccentricity(e_min, e_max, ef, m_prim+m_sec);
00512
00513
00514
00515 determine_semi_major_axis_limits(m_prim, m_sec, ecc, a_min, a_max);
00516
00517 semi = get_random_semimajor_axis(a_min, a_max, af, a_exp, m_prim, m_sec);
00518
00519
00520
00521
00522
00523
00524
00525 }
00526
00527
00528 void print_initial_binary_distributions(real m_min, real m_max,
00529 mass_function mf, real m_exp,
00530 real q_min, real q_max,
00531 mass_ratio_distribution qf,
00532 real q_exp,
00533 real a_min, real a_max,
00534 sma_distribution af, real a_exp,
00535 real e_min, real e_max,
00536 ecc_distribution ef, real e_exp) {
00537
00538
00539 cout << "Use the following initial distribution functions:" << endl;
00540 cout << " -Mass function is " << type_string(mf);
00541 if(mf==mf_Power_Law)
00542 cout << " with exponent " << m_exp;
00543
00544 if(mf==Equal_Mass)
00545 cout << " with value " << m_min << endl;
00546 else
00547 cout << "\n between "
00548 << m_min << " and " << m_max << endl;
00549 cout << " -mass-ratio distribution is " << type_string(qf);
00550 if(qf==qf_Power_Law)
00551 cout << " with exponent " << q_exp;
00552
00553 if (qf==Equal_q)
00554 cout << " with value " << q_min << endl;
00555 else if (qf!=Flat_q)
00556 cout << endl;
00557 else
00558 cout << "\n between "
00559 << q_min << " and " << q_max << endl;
00560
00561 cout << " -Semi-major axis distribution is " << type_string(af);
00562 if(af==sma_Power_Law)
00563 cout << " with exponent " << a_exp;
00564
00565 if(af==Equal_sma)
00566 cout << " with value " << a_min << endl;
00567 else
00568 cout << "\n between "
00569 << a_min << " and " << a_max << endl;
00570 cout << " -eccenctriciy distribution is " << type_string(ef);
00571 real e_lower = 0;
00572 if (e_min>=0) e_lower=e_min;
00573 if(ef==ecc_Power_Law)
00574 cout << " with exponent " << e_exp;
00575
00576 if(ef==Equal_ecc)
00577 cout << " with value " << e_lower << endl;
00578 else
00579 cout << "\n between "
00580 << e_lower << " and " << e_max << endl;
00581 }
00582
00583
00584 void adddouble(node * b, real dyn_time,
00585 binary_type type,
00586 bool random_initialization,
00587 real a_min, real a_max,
00588 real e_min, real e_max)
00589 {
00590 if (REPORT_ADD_DOUBLE) {
00591 int p = cerr.precision(HIGH_PRECISION);
00592 cerr<<"adddouble: "<<b<<" "<<dyn_time;
00593 cerr.precision(p);
00594 cerr <<" "<<a_min<<" "<<a_max<<" "<<e_min<<" "<<e_max << endl;
00595 }
00596
00597 real stellar_time = b->get_starbase()->conv_t_dyn_to_star(dyn_time);
00598 cerr << "addstar(node... called from adddouble(node ..." << endl;
00599 addstar(b, stellar_time, Main_Sequence);
00600
00601 real ecc, sma;
00602
00603
00604 int id;
00605 real a_const = log(a_max) - log(a_min);
00606 for_all_nodes(node, b, bi) {
00607 if (bi->is_parent() && !bi->is_root()) {
00608 story * s = b->get_starbase()->get_star_story();
00609
00610 b->get_starbase()->set_star_story(NULL);
00611 delete s;
00612
00613 id = bi->get_index();
00614
00615 if (random_initialization) {
00616 sma = a_min*exp(randinter(0., a_const));
00617 do {
00618 ecc = sqrt(randinter(0., 1.));
00619 }
00620 while (ecc<e_min || ecc>=e_max);
00621 }
00622 else {
00623
00624
00625 id = bi->get_index();
00626 sma = a_min*exp(randinter(0., a_const));
00627 do {
00628 ecc = sqrt(randinter(0., 1.));
00629 }
00630 while (ecc<e_min || ecc>=e_max);
00631 }
00632 if (REPORT_ADD_DOUBLE)
00633 cerr<<"adddouble: iae: "<<id<<" "<<sma<<" "<<ecc<<endl;
00634
00635 double_star* new_double = new_double_star(bi, sma, ecc, stellar_time, id,
00636 type);
00637 if (REPORT_ADD_DOUBLE) {
00638 cerr<<"double: "<<new_double<<endl;
00639 new_double->dump(cerr);
00640 put_state(make_state(new_double));
00641 }
00642 }
00643 }
00644 }
00645 #else
00646
00647 void main(int argc, char ** argv) {
00648
00649 bool F_flag = false;
00650 bool P_flag = false;
00651 bool U_flag = false;
00652 bool G_flag = false;
00653 char *mfc = new char[64];
00654 mass_function mf = mf_Power_Law;
00655 real m_min = 0.1;
00656 real m_max = 100;
00657 real m_exp = -2.35;
00658 char *qfc = new char[64];
00659 mass_ratio_distribution qf = Flat_q;
00660 real q_min = 0;
00661 real q_max = 1;
00662 real q_exp = 0;
00663 char *afc = new char[64];
00664 sma_distribution af = sma_Power_Law;
00665 real a_min = 0;
00666 real a_max = 1.e+6;
00667 real a_exp = -1;
00668 char *efc = new char[64];
00669 ecc_distribution ef = Thermal_Distribution;
00670 real e_min = -1;
00671 real e_max = 1;
00672 real e_exp;
00673
00674 int n = 1;
00675
00676 int random_seed = 0;
00677 char seedlog[64];
00678
00679 check_help();
00680
00681 extern char *poptarg;
00682 int c;
00683 char* param_string = "M:m:x:F:f:A:a:y:G:g:E:e:v:U:u:Q:q:w:P:p:n:";
00684
00685 while ((c = pgetopt(argc, argv, param_string)) != -1)
00686 switch(c) {
00687 case 'M': m_max = atof(poptarg);
00688 break;
00689 case 'm': m_min = atof(poptarg);
00690 break;
00691 case 'x': m_exp = atof(poptarg);
00692 break;
00693 case 'F': F_flag = true;
00694 strcpy(mfc, poptarg);
00695 break;
00696 case 'f': mf = (mass_function)atoi(poptarg);
00697 break;
00698 case 'A': a_max = atof(poptarg);
00699 break;
00700 case 'a': a_min = atof(poptarg);
00701 break;
00702 case 'y': a_exp = atof(poptarg);
00703 break;
00704 case 'G': G_flag = true;
00705 strcpy(afc, poptarg);
00706 break;
00707 case 'g': af = (sma_distribution)atoi(poptarg);
00708 break;
00709 case 'E': e_max = atof(poptarg);
00710 break;
00711 case 'e': e_min = atof(poptarg);
00712 break;
00713 case 'v': e_exp = atof(poptarg);
00714 break;
00715 case 'U': U_flag = true;
00716 strcpy(efc, poptarg);
00717 break;
00718 case 'u': ef = (ecc_distribution)atoi(poptarg);
00719 break;
00720 case 'Q': q_max = atof(poptarg);
00721 break;
00722 case 'q': q_min = atof(poptarg);
00723 break;
00724 case 'w': q_exp = atof(poptarg);
00725 break;
00726 case 'P': P_flag = true;
00727 strcpy(qfc, poptarg);
00728 break;
00729 case 'p': qf = (mass_ratio_distribution)atoi(poptarg);
00730 break;
00731 case 'n': n = atoi(poptarg);
00732 break;
00733 case 's': random_seed = atoi(poptarg);
00734 break;
00735 case '?': params_to_usage(cerr, argv[0], param_string);
00736 exit(1);
00737 }
00738
00739 int actual_seed = srandinter(random_seed);
00740 printf("random number generator seed = %d\n",actual_seed);
00741
00742
00743
00744
00745 if(F_flag)
00746 mf = extract_mass_function_type_string(mfc);
00747 delete mfc;
00748 if(G_flag)
00749 af = extract_semimajor_axis_distribution_type_string(afc);
00750 delete afc;
00751 if(U_flag)
00752 ef = extract_eccentricity_distribution_type_string(efc);
00753 delete efc;
00754 if(P_flag)
00755 qf = extract_mass_ratio_distribution_type_string(qfc);
00756 delete qfc;
00757
00758 real m_prim, m_sec, sma, ecc;
00759 cerr << "\tM\tm\ta\te"<<endl;
00760 for (int i=0; i<n; i++) {
00761 mkrandom_binary(m_min, m_max, mf, m_exp,
00762 q_min, q_max, qf, q_exp,
00763 a_min, a_max, af, a_exp,
00764 e_min, e_max, ef, e_exp,
00765 m_prim, m_sec, sma, ecc);
00766 cout << "\t" << m_prim
00767 << "\t" << m_sec
00768 << "\t" << sma
00769 << "\t" << ecc << endl;
00770 }
00771
00772 }
00773 #endif
00774