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 #include "dstar_to_kira.h"
00059
00060 #define REPORT_ADD_DOUBLE false
00061 #define REPORT_DEL_DOUBLE false
00062 #define REPORT_EVOLVE_DOUBLE false
00063
00064 local bool need_dstar(hdyn* bi)
00065 {
00066 if (bi->is_low_level_node() && (bi->get_elder_sister() == NULL)
00067 && (bi->get_kepler() != NULL) && bi->get_fully_unperturbed()) {
00068 return true;
00069 } else {
00070 return false;
00071 }
00072 }
00073
00074
00075 bool other_urgent_binary_matters(hdyn *bi)
00076 {
00077 bool update_binary = false;
00078
00079 starbase *cm = bi->get_starbase();
00080 starbase *ps = ((star*)cm)->get_primary();
00081 starbase *ss = ((star*)cm)->get_secondary();
00082
00083 real pericenter = cm->get_semi()*(1-cm->get_eccentricity());
00084
00085 real rp = ps->get_effective_radius();
00086 real rs = ss->get_effective_radius();
00087
00088 if(pericenter <= rp * cnsts.parameters(tidal_circularization_radius) ||
00089 pericenter <= rs * cnsts.parameters(tidal_circularization_radius)) {
00090
00091 update_binary = true;
00092 }
00093
00094 return update_binary;
00095 }
00096
00097
00098 local bool binary_wants_to_be_updated(hdyn *b)
00099 {
00100 bool update_binary = false;
00101
00102 hdyn* od = b->get_oldest_daughter();
00103 real stellar_time = b->get_starbase()
00104 ->conv_t_dyn_to_star(od->get_time());
00105
00106 real current_age = b->get_starbase()->get_current_time();
00107 real dt_max = b->get_starbase()->get_evolve_timestep();
00108
00109
00110 if (stellar_time >= current_age
00111 + cnsts.star_to_dyn(binary_update_time_fraction)*dt_max)
00112 update_binary = true;
00113
00114
00115
00116
00117
00118 return update_binary;
00119 }
00120
00121 local void evolve_an_unperturbed_binary(hdyn *bi,
00122 bool& check_binary_mass,
00123 bool& check_binary_sma,
00124 bool& check_binary_merger,
00125 bool force_evolve=false)
00126 {
00127 check_binary_mass = check_binary_sma = check_binary_merger = false;
00128
00129 real old_dyn_mass, old_dyn_sma;
00130 real new_dyn_mass_from_star, new_dyn_sma_from_star;
00131
00132 hdyn* od = bi->get_oldest_daughter();
00133 real stellar_evolution_time = bi->get_starbase()
00134 ->conv_t_dyn_to_star(od->get_time());
00135
00136
00137 kepler * p_kep = od->get_kepler();
00138 old_dyn_mass = bi->get_mass();
00139 old_dyn_sma = p_kep->get_semi_major_axis();
00140
00141 if (REPORT_EVOLVE_DOUBLE) {
00142 cerr << "Before evolution:"
00143 << " sma= " << bi->get_starbase()->get_semi()
00144 << " ecc= " << bi->get_starbase()->get_eccentricity()
00145 << " Time = "<<stellar_evolution_time <<" ";
00146 put_state(make_state(dynamic_cast(double_star*, bi->get_starbase())));
00147 cerr << endl;
00148 ((double_star*) (bi->get_starbase()))->dump(cerr);
00149 cerr << endl;
00150 }
00151
00152 if (!force_evolve) {
00153 if (binary_wants_to_be_updated(bi))
00154 bi->get_starbase()->evolve_element(stellar_evolution_time);
00155 else
00156 ((double_star*)(bi->get_starbase()))->try_zero_timestep();
00157 }
00158 else
00159 bi->get_starbase()->evolve_element(stellar_evolution_time);
00160
00161 new_dyn_mass_from_star = get_total_mass(bi);
00162 new_dyn_sma_from_star = bi->get_starbase()->
00163 conv_r_star_to_dyn(bi->get_starbase()->get_semi());
00164
00165
00166
00167
00168 if (abs(new_dyn_mass_from_star-old_dyn_mass)/old_dyn_mass
00169 >=cnsts.star_to_dyn(stellar_mass_update_limit)) {
00170 check_binary_mass=true;
00171 }
00172 if (abs(new_dyn_sma_from_star-old_dyn_sma)/old_dyn_sma
00173 >=cnsts.star_to_dyn(semi_major_axis_update_limit)) {
00174 check_binary_sma=true;
00175 }
00176 if (binary_is_merged(od)) {
00177 cerr << endl << "evolve_an_unperturbed_binary: binary "
00178 << bi->format_label()
00179 << " is apparently merged" << endl;
00180 check_binary_merger = true;
00181 }
00182
00183 star * primary = ((star*) (bi->get_starbase()))->get_primary();
00184 star * secondary = ((star*) (bi->get_starbase()))->get_secondary();
00185 real m1 = primary->get_total_mass();
00186 real m2 = secondary->get_total_mass();
00187 real semi = bi->get_starbase()->get_semi();
00188 real ecc = bi->get_starbase()->get_eccentricity();
00189 char * t1 = type_string(primary->get_element_type());
00190 char * t2 = type_string(secondary->get_element_type());
00191
00192 if (REPORT_EVOLVE_DOUBLE)
00193 if (check_binary_sma || check_binary_mass || check_binary_merger) {
00194 cerr << " check: "
00195 <<check_binary_mass<<" "
00196 <<check_binary_sma<<" "
00197 <<check_binary_merger<<endl;
00198 bi->pretty_print_node(cerr); PRC(bi->get_time());
00199 PRL(od->get_time());
00200 PRC(bi->get_system_time()); PRL(stellar_evolution_time);
00201 PRC(t1); PRC(m1); PRC(t2); PRC(m2); PRC(semi); PRL(ecc);
00202 cerr << "After evolution:"
00203 << " sma= " << semi
00204 << " ecc= " << ecc
00205 << " Time = "<<stellar_evolution_time <<" ";
00206 put_state(make_state(dynamic_cast(double_star*,
00207 bi->get_starbase())));
00208 cerr << endl;
00209 ((double_star*) (bi->get_starbase()))->dump(cerr);
00210 cerr << endl;
00211 }
00212
00213
00214 }
00215
00216 local real initial_binary_period(double_star * ds)
00217 {
00218 double_init *di = ds->get_initial_conditions();
00219
00220 real pdays = 2*PI*sqrt(pow(di->semi*cnsts.parameters(solar_radius), 3.)
00221 / (cnsts.physics(G)*di->mass_prim
00222 *(1+di->q)*cnsts.parameters(solar_mass)))
00223 / cnsts.physics(days);
00224 return pdays;
00225 }
00226
00227
00228
00229 local void delete_double(hdyn *b)
00230 {
00231 if (REPORT_DEL_DOUBLE) {
00232 cerr << "Unsafe double_star deletion: "<<endl;
00233 b->pretty_print_node(cerr); cerr << endl;
00234 ((star*)(b->get_starbase()))->dump(cerr);
00235 }
00236 double_star *the_binary = dynamic_cast(double_star*, b->get_starbase());
00237
00238
00239
00240
00241
00242
00243 hdyn* od = b->get_oldest_daughter();
00244 real stellar_time = b->get_starbase()
00245 ->conv_t_dyn_to_star(od->get_time());
00246
00247 the_binary->evolve_the_binary(stellar_time);
00248 the_binary->set_node(NULL);
00249
00250 story* old_story = the_binary->get_star_story();
00251 the_binary->set_star_story(NULL);
00252
00253 if (old_story)
00254 delete old_story;
00255
00256
00257
00258
00259
00260
00261 delete the_binary;
00262
00263
00264
00265
00266
00267 b->set_starbase(new starbase());
00268 b->get_starbase()->set_node(b);
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 local void delete_double(hdyn *b,
00289 bool * update_dynamics,
00290 bool allow_evolution_before_termination,
00291 int full_dump = 0)
00292 {
00293 if (b->get_oldest_daughter()->get_kepler() == NULL) {
00294 cerr << "Deleting double without a kepler pointer"<<endl;
00295 delete_double(b);
00296 return;
00297 }
00298
00299
00300
00301 bool kepler_created = false;
00302
00303 hdyn* od = b->get_oldest_daughter();
00304 if (!od->get_kepler()) {
00305
00306
00307
00308 cerr << "No Kepler in delete_double; create one."<<endl;
00309 new_child_kepler(b, od->get_time(), MAX_CIRC_ECC);
00310 kepler_created = true;
00311 }
00312 else {
00313 od->get_kepler()->
00314 set_circular_binary_limit(MAX_CIRC_ECC);
00315 dyn_to_child_kepler(b, od->get_time());
00316 }
00317
00318 if (REPORT_DEL_DOUBLE) {
00319 cerr << "kepler created in delete_double ";
00320 cerr << "at address " << od->get_kepler()
00321 << endl;
00322 }
00323
00324 kepler* johannes = od->get_kepler();
00325
00326 if (REPORT_DEL_DOUBLE) {
00327 cerr << "delete double star "; b->pretty_print_node(cerr);
00328 cerr<<endl;
00329 ((double_star*)(b->get_starbase()))->dump(cerr);
00330 }
00331
00332 double_star *the_binary = dynamic_cast(double_star*, b->get_starbase());
00333
00334 if (REPORT_DEL_DOUBLE)
00335 put_state(make_state(the_binary));
00336
00337
00338
00339 real stellar_time = b->get_starbase()
00340 ->conv_t_dyn_to_star(od->get_time());
00341
00342
00343 bool change_mass = false, change_sma = false, check_merger = false;
00344 bool force_evolve = true;
00345
00346
00347
00348
00349
00350 if (allow_evolution_before_termination) {
00351
00352 evolve_an_unperturbed_binary(b,
00353 change_mass,
00354 change_sma,
00355 check_merger,
00356 force_evolve);
00357 }
00358
00359 update_dynamics[0] |= (change_mass || change_sma);
00360
00361 if (REPORT_DEL_DOUBLE) {
00362 PRL(update_dynamics[0]);
00363 the_binary->dump(cerr);
00364 put_state(make_state(the_binary));
00365 }
00366
00367 if (check_merger) {
00368
00369 hdyn* bcoll = od->get_binary_sister();
00370
00371 cerr <<"delete_double: merger within "
00372 << b->format_label()
00373 << " triggered by ";
00374 cerr << bcoll->format_label();
00375 int p = cerr.precision(INT_PRECISION);
00376 cerr << " at time (tsys)" << b->get_system_time()
00377 << "(binary: "<< od->get_time() <<")"<< endl;
00378 cerr.precision(p);
00379
00380
00381
00382 od->merge_nodes(bcoll, full_dump);
00383 update_dynamics[0] = true;
00384
00385
00386
00387
00388
00389
00390
00391 if (RESOLVE_UNPERTURBED_PERTURBERS) {
00392 hdynptr del[2];
00393 del[0] = od;
00394 del[1] = bcoll;
00395 correct_perturber_lists(b->get_root(), del, 2, b);
00396 }
00397
00398 if (kepler_created) delete johannes;
00399
00400 delete od;
00401 delete bcoll;
00402
00403 delete the_binary;
00404
00405 return;
00406 }
00407 else {
00408
00409
00410
00411
00412
00413 if (the_binary->get_period()
00414 / initial_binary_period(the_binary) < 0.9) {
00415 real dm_fast = sudden_mass_loss(b);
00416 update_kepler_from_binary_evolution(b, dm_fast);
00417 update_dynamics[1] = true;
00418 if (REPORT_DEL_DOUBLE)
00419 PRL(update_dynamics[1]);
00420 }
00421
00422
00423
00424
00425
00426
00427 story* old_story = the_binary->get_star_story();
00428 the_binary->set_star_story(NULL);
00429
00430 if (old_story)
00431 delete old_story;
00432
00433
00434
00435
00436
00437
00438 the_binary->set_node(NULL);
00439 delete the_binary;
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 b->set_starbase(new starbase());
00461 b->get_starbase()->set_node(b);
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471 }
00472
00473 if (kepler_created) {
00474 if (od->get_kepler()) {
00475 od->set_kepler(NULL);
00476 od->get_binary_sister()->set_kepler(NULL);
00477 delete johannes;
00478 }
00479 }
00480 }
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 bool create_or_delete_binary(hdyn *bi,
00491 bool * update_dynamics,
00492 int full_dump )
00493 {
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503 if (REPORT_ADD_DOUBLE || REPORT_DEL_DOUBLE )
00504 cerr << "create_or_delete_binary" << endl;
00505
00506 if (has_dstar(bi->get_oldest_daughter())) {
00507 if (REPORT_DEL_DOUBLE )
00508 cerr << "Delete existing binary from "
00509 << bi->format_label()<<endl;
00510
00511
00512
00513
00514
00515 bool allow_evolution_before_termination = false;
00516
00517 delete_double(bi, update_dynamics,
00518 allow_evolution_before_termination,
00519 full_dump);
00520
00521
00522
00523 return true;
00524 }
00525 else {
00526 if (REPORT_ADD_DOUBLE)
00527 cerr << "Create new binary to "
00528 << bi->format_label()<<endl;
00529
00530 adddouble(bi, bi->get_oldest_daughter()->get_time());
00531
00532
00533
00534
00535 return true;
00536 }
00537
00538 return false;
00539 }
00540
00541 bool binary_is_merged(dyn* bi)
00542 {
00543 starbase * p_star = bi->get_parent()->get_starbase();
00544 if (bi->get_kepler()
00545 && p_star->get_element_type()==Double) {
00546 if (p_star->get_bin_type()==Merged)
00547 return true;
00548 }
00549 return false;
00550 }
00551
00552 bool binary_evolution(hdyn *b,
00553 int full_dump)
00554
00555
00556
00557
00558 {
00559 bool update_dynamics[2] = {false, false};
00560
00561
00562
00563
00564
00565
00566 for_all_leaves(hdyn, b, bi) {
00567
00568 if (need_dstar(bi) && (! has_dstar(bi))) {
00569
00570 hdyn * parent = bi->get_parent();
00571
00572 create_or_delete_binary(bi->get_parent(),
00573 update_dynamics, full_dump);
00574
00575 if (REPORT_ADD_DOUBLE) {
00576 cerr << "new double star created at time "
00577 << bi->get_time()<<endl;
00578 pp3(parent, cerr);
00579 }
00580 }
00581
00582 if (has_dstar(bi)) {
00583
00584 if (need_dstar(bi)) {
00585
00586 if (binary_wants_to_be_updated(bi->get_parent())) {
00587
00588 if (REPORT_EVOLVE_DOUBLE)
00589 cerr << "\nEvolving binary " << bi->format_label()
00590 << endl;
00591
00592
00593
00594
00595 bool change_mass, change_sma, check_merger;
00596 bool force_evolve = false;
00597
00598 evolve_an_unperturbed_binary(bi->get_parent(),
00599 change_mass,
00600 change_sma,
00601 check_merger,
00602 force_evolve);
00603
00604 update_dynamics[0] |= (change_mass || change_sma);
00605
00606 if (REPORT_DEL_DOUBLE)
00607 PRL(update_dynamics[0]);
00608
00609 if (check_merger) {
00610
00611 hdyn* par = bi->get_parent();
00612 hdyn* bcoll = bi->get_binary_sister();
00613
00614 cerr << "binary_evolution: merger within "
00615 << par->format_label()
00616 << " triggered by ";
00617 cerr << bcoll->format_label();
00618 int p = cerr.precision(INT_PRECISION);
00619 cerr << " at time " << b->get_time() << endl;
00620 cerr.precision(p);
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630 bi->merge_nodes(bcoll, full_dump);
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642 if (RESOLVE_UNPERTURBED_PERTURBERS) {
00643 hdynptr del[2];
00644 del[0] = bi;
00645 del[1] = bcoll;
00646 cerr << "correcting perturber lists"
00647 << endl << flush;
00648 correct_perturber_lists(par->get_root(),
00649 del, 2, par);
00650 }
00651
00652 delete bi;
00653 delete bcoll;
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673 update_dynamics[0] = true;
00674 bi = par;
00675 }
00676 }
00677
00678 } else {
00679
00680 if (REPORT_DEL_DOUBLE) {
00681 cerr << "delete double star at time "
00682 << bi->get_time() << endl;
00683 pp3(bi->get_parent(), cerr);
00684 PRL(bi->is_low_level_node());PRL(bi->get_elder_sister());
00685 PRL(bi->get_kepler());PRL(bi->get_fully_unperturbed());
00686 PRL(need_dstar(bi));PRL(has_dstar(bi));
00687 }
00688
00689
00690
00691
00692
00693
00694
00695 create_or_delete_binary(bi->get_parent(),
00696 update_dynamics, full_dump);
00697 }
00698 }
00699 }
00700
00701 return update_dynamics[0];
00702 }
00703
00704 void update_kepler_from_binary_evolution(hdyn* the_binary_node,
00705 real dm_fast)
00706 {
00707 if (REPORT_EVOLVE_DOUBLE)
00708 ((double_star*)(the_binary_node->get_starbase()))->dump(cerr);
00709
00710 kepler *johannes = the_binary_node->get_oldest_daughter()->get_kepler();
00711 real sma = the_binary_node->get_starbase()->conv_r_star_to_dyn(
00712 the_binary_node->get_starbase()->get_semi());
00713 real ecc = the_binary_node->get_starbase()->get_eccentricity();
00714
00715 real m_total = get_total_mass(the_binary_node) - dm_fast;
00716
00717 real mean_anomaly = johannes->get_mean_anomaly();
00718
00719
00720 real peri = sma * (1-ecc);
00721 hdyn * b = the_binary_node->get_oldest_daughter();
00722 johannes->transform_to_time(b->get_time());
00723
00724 real time = johannes->get_time();
00725 if (REPORT_EVOLVE_DOUBLE) {
00726 PRC(time); PRC(sma); PRL(m_total); PRC(mean_anomaly); PRL(peri);
00727 }
00728
00729 make_standard_kepler(*johannes, time, m_total, -0.5 * m_total / sma, ecc,
00730 peri, mean_anomaly, 0);
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742 johannes->pred_advance_to_periastron();
00743
00744 if (johannes->get_pred_time() < b->get_time()) {
00745 cerr << "update_kepler_from_binary, time went backwards"<<endl;
00746 PRC(the_binary_node->format_label());
00747 PRC(johannes->get_pred_time()); PRL(b->get_time());
00748 }
00749 }