diff --git a/src/binary_c_function_macros.h b/src/binary_c_function_macros.h index 11522bb72ba0b0079f3ba568f63d0744d95e12d7..7c35b432bb98639c698efcd9ca48d3dbaa5a51cc 100644 --- a/src/binary_c_function_macros.h +++ b/src/binary_c_function_macros.h @@ -475,6 +475,8 @@ #define System_is_single _System_is_single(stardata) #define System_is_binary _System_is_binary(stardata) +#define System_was_single _System_is_single(stardata->previous_stardata) +#define System_was_binary _System_is_binary(stardata->previous_stardata) /* * Define an observable binary as one in which diff --git a/src/binary_c_structures.h b/src/binary_c_structures.h index 5420c8318d7c3374e731a078935bf301f10049b3..8e2f3a58d34c1c132f2c898acaa1a4867f28f710 100644 --- a/src/binary_c_structures.h +++ b/src/binary_c_structures.h @@ -987,6 +987,9 @@ struct preferences_t { double orbiting_objects_close_pc_threshold; #endif // ORBITING_OBJECTS +#ifdef EVOLUTION_SPLITTING + double evolution_splitting_sn_eccentricity_threshold; +#endif /* * Strings (e.g. Filenames) diff --git a/src/evolution/evolution_split.c b/src/evolution/evolution_split.c index 2e30b946fc6766c1f708ad3338b6d7d4c8f55fb9..4682c1f8d44005dc6201d17f4aae7d4cb2547a52 100644 --- a/src/evolution/evolution_split.c +++ b/src/evolution/evolution_split.c @@ -165,8 +165,9 @@ int evolution_split(struct stardata_t * RESTRICT const stardata, stardata->star[1].stellar_type ); Append_logstring(LOG_SPLIT_EVOLUTION, - "Evolution restart @ t=%g, %d.%d", + "Evolution restart @ t=%g, prev e=%g, %d.%d", stardata->model.time, + stardata->previous_stardata->common.orbit.eccentricity, stardata->preferences->current_splitdepth-1, p->count); #ifdef LINUX @@ -290,8 +291,9 @@ int evolution_split(struct stardata_t * RESTRICT const stardata, stardata->model.doingsplit = TRUE; Append_logstring(LOG_SPLIT_EVOLUTION, - "Evolution split and restart at t=%g, %d.%d", + "Evolution split and restart at t=%g, prev e=%g, %d.%d", stardata->model.time, + stardata->previous_stardata->common.orbit.eccentricity, stardata->preferences->current_splitdepth-1, p->count); @@ -322,10 +324,6 @@ int evolution_split(struct stardata_t * RESTRICT const stardata, static int splittest(struct stardata_t * RESTRICT const stardata) { - struct stardata_t * previous_stardata = stardata->previous_stardata; - int split = 0; - Star_number i; - /* * Detect new split cases after stellar evolution has * been done in this system. You can use stardata and @@ -338,25 +336,28 @@ static int splittest(struct stardata_t * RESTRICT const stardata) * Returns zero if there should be no split. */ - Starloop(i) + Foreach_star(star) { - if(!split) + /* + * Supernova check + */ + SDEBUG("check SN %d : type %d\n", + stardata->model.supernova, + star->stellar_type); + + const Boolean supernova = + stardata->model.supernova || + ((star->stellar_type == BLACK_HOLE || + star->stellar_type == NEUTRON_STAR) && + (stardata->previous_stardata->star[star->starnum].stellar_type<=HeGB)); + + if(supernova == TRUE && + supernova_should_split_evolution(stardata)) { - // Supernova - SDEBUG("check SN %d : type %d\n", - stardata->model.supernova, - stardata->star[i].stellar_type); - - if(stardata->model.supernova || - ((stardata->star[i].stellar_type == BLACK_HOLE || - stardata->star[i].stellar_type == NEUTRON_STAR) && - (previous_stardata->star[i].stellar_type<=HeGB))) - { - split = stardata->preferences->evolution_splitting_sn_n; - } + return stardata->preferences->evolution_splitting_sn_n; } } - return split; + return 0; } static void modulate_stardata(struct stardata_t * RESTRICT const stardata, diff --git a/src/evolution/evolve_system_binary_c.c b/src/evolution/evolve_system_binary_c.c index 45c10be27435c3de5f7fa19669bb8842e01ef3ad..836a42ea74dc73862cb9361560abe83797c2c3bf 100644 --- a/src/evolution/evolve_system_binary_c.c +++ b/src/evolution/evolve_system_binary_c.c @@ -287,7 +287,6 @@ int evolve_system_binary_c(struct stardata_t * RESTRICT const stardata) */ Evolution_logging; - /* * Update timestep triggers */ diff --git a/src/setup/cmd_line_args_list.h b/src/setup/cmd_line_args_list.h index bff99ffe944b3e3fae7d07d5cbe94eb0ef5c5672..2f959e2d0d7c575a5b8beb796aade3fbace94715 100644 --- a/src/setup/cmd_line_args_list.h +++ b/src/setup/cmd_line_args_list.h @@ -952,6 +952,15 @@ BATCHMODE_ARGS Var(stardata->preferences->disable_events), 1.0 CMD_LINE_ARG_T_OPTIONAL_ARGS }, +{ + ARG_SECTION_STARS, + "evolution_splitting_sn_eccentricity_threshold", + "Threshold eccentricity above which evolution splitting happens in a system with no SN kick. (0.01)", + ARG_FLOAT , + WTTS_USE_DEFAULT, + EVOLUTION_SPLITTING_SN_ECCENTRICITY_THRESHOLD_VAR, + 1.0 + CMD_LINE_ARG_T_OPTIONAL_ARGS }, { ARG_SECTION_STARS, diff --git a/src/setup/cmd_line_macros.h b/src/setup/cmd_line_macros.h index 25f47570b2dd8d9cfc2f0c8eeee6d741118bb5c3..8837d55a40024813aeb913fbeb007b38b9f39d35 100644 --- a/src/setup/cmd_line_macros.h +++ b/src/setup/cmd_line_macros.h @@ -298,10 +298,12 @@ #define EVOLUTION_SPLITTING_VAR Var(stardata->preferences->evolution_splitting) #define EVOLUTION_SPLITTING_MAXDEPTH_VAR Var(stardata->preferences->evolution_splitting_maxdepth) #define EVOLUTION_SPLITTING_SN_N_VAR Var(stardata->preferences->evolution_splitting_sn_n) +#define EVOLUTION_SPLITTING_SN_ECCENTRICITY_THRESHOLD_VAR Var(stardata->preferences->evolution_splitting_sn_eccentricity_threshold) #else #define EVOLUTION_SPLITTING_VAR Not_used_arg #define EVOLUTION_SPLITTING_SN_N_VAR Not_used_arg #define EVOLUTION_SPLITTING_MAXDEPTH_VAR Not_used_arg +#define EVOLUTION_SPLITTING_SN_ECCENTRICITY_THRESHOLD_VAR Not_used_arg #endif #ifdef DISCS diff --git a/src/setup/set_default_preferences.c b/src/setup/set_default_preferences.c index 55b634bcbce30677695306145d7c3fa09e691ae5..4fd7e5ab3ee41760da4fd46eab745d3540dd1d7e 100644 --- a/src/setup/set_default_preferences.c +++ b/src/setup/set_default_preferences.c @@ -18,7 +18,8 @@ void set_default_preferences(struct preferences_t * RESTRICT const preferences) * * to list the default parameters. * - * Beware that these defaults are not + * The preferences struct is allocated using Calloc, + * so everything is zero by default. */ timestep_set_default_multipliers(preferences); #ifdef TIMESTEP_MODULATION @@ -427,6 +428,7 @@ preferences->WD_accretion_rate_novae_upper_limit_other_donor = ACCRETION_RATE_NO #ifdef EVOLUTION_SPLITTING preferences->evolution_splitting_sn_n = EVOLUTION_SPLITTING_SUPERNOVA_N; preferences->evolution_splitting_maxdepth = EVOLUTION_SPLITTING_MAX_SPLITDEPTH_DEFAULT; + preferences->evolution_splitting_sn_eccentricity_threshold = 0.01; #endif // EVOLUTION_SPLITTING #ifdef DISCS #if defined DISC_LOG || defined DISC_LOG_2D diff --git a/src/supernovae/set_kick_velocity.c b/src/supernovae/set_kick_velocity.c index 468c84e87b34182ecd99674d802b1c2863935fd2..a48cacbe0c419cbab655be5fce5558b88bad7b2a 100644 --- a/src/supernovae/set_kick_velocity.c +++ b/src/supernovae/set_kick_velocity.c @@ -35,13 +35,12 @@ void set_kick_velocity(struct stardata_t * const stardata, * Use Henon's method for pairwise components (Douglas Heggie 22/5/97). */ #if defined TEST_KICK_SPEED_DISTRIBUTION || defined TEST_KICK_DIRECTIONS - int il; - for(il=0;il<NTESTS;il++) + for(int il=0;il<NTESTS;il++) { #endif double u1=0.0,v[5]; // v is the kick velocity vector unsigned int k; - for (k=1; k<=2; k++) + for (k=1; k<3; k++) { u1 = (double)random_number(stardata,random_seed); double u2 = (double)random_number(stardata,random_seed); diff --git a/src/supernovae/supernova_should_split_evolution.c b/src/supernovae/supernova_should_split_evolution.c new file mode 100644 index 0000000000000000000000000000000000000000..37eeadaa1cb1caafd81da5324a57f637a1c0d924 --- /dev/null +++ b/src/supernovae/supernova_should_split_evolution.c @@ -0,0 +1,71 @@ +#include "../binary_c.h" +No_empty_translation_unit_warning; + +#include "supernovae.h" + +Boolean supernova_should_split_evolution(struct stardata_t * const stardata) +{ + /* + * This function returns TRUE if evolution splitting + * should happen. This is based on a possibly complicated + * set of logical decisions. + * + * Note: we must check both stars for supernovae, + * and we should use the previous_stardata to + * check the orbit (e.g. eccentricity, duplicity) + * because the stardata we have now has already + * had a kick if there was a suitable supernova. + */ + + /* + * We don't need to split single stars: their + * orbit cannot be sampled and their kick + * speed is (probably) irrelevant. + */ + if(System_was_binary) + { + Foreach_star(star) + { + if(star->SN_type != SN_NONE) + { + /* + * If the orbit is eccentric, we should split to + * sample different anomalies regardless of the + * kick speed. + */ + if(stardata->previous_stardata->common.orbit.eccentricity > + stardata->preferences->evolution_splitting_sn_eccentricity_threshold) + { + return TRUE; + } + + /* + * If there is a Maxwellian kick, with non-zero dispersion, + * splitting should happen because the kick speed is random. + */ + else if( + stardata->preferences->sn_kick_distribution[star->SN_type] == KICK_VELOCITY_MAXWELLIAN + && + Is_not_zero(stardata->preferences->sn_kick_dispersion[star->SN_type]) + ) + { + return TRUE; + } + + /* + * If the kick is a custom function, we should split just + * in case. + */ + else if(stardata->preferences->sn_kick_distribution[star->SN_type] == KICK_VELOCITY_CUSTOM) + { + return TRUE; + } + } + } + } + + /* + * ... no criteria are satisfied, so no splitting is required. + */ + return FALSE; +} diff --git a/src/supernovae/supernovae_prototypes.h b/src/supernovae/supernovae_prototypes.h index 6a3626bc24370f8f844a6eae3deec1cdebd1063e..b6e7c5b4f5130be7eece8dab8978c1f0160b6b95 100644 --- a/src/supernovae/supernovae_prototypes.h +++ b/src/supernovae/supernovae_prototypes.h @@ -97,4 +97,6 @@ Yield_source supernova_source_id(struct star_t * exploder, struct star_t * pre_explosion_star, struct star_t * companion); +Boolean supernova_should_split_evolution(struct stardata_t * const stardata); + #endif // SUPERNOVA_PROTOTYPES_H diff --git a/tbse b/tbse index 6efea3001e0a8340aaf7ca28bbb92793da04986e..d9afcb9155b29c1aedb7acaca8853f607a7fca47 100755 --- a/tbse +++ b/tbse @@ -1316,10 +1316,14 @@ SN_KICK_COMPANION_IA_Hybrid_HeCOWD_subluminous=SN_IMPULSE_NONE # when a SN occurs. # (If this is 1, then the evolution is as normal.) # +# The evolution splitting algorithm has code to detect whether +# a split should happen when there is a supernova. You have to choose +# an eccentricity above which splitting happens in +# evolution_splitting_sn_eccentricity_threshold EVOLUTION_SPLITTING=False EVOLUTION_SPLITTING_MAXDEPTH=2 EVOLUTION_SPLITTING_SN_N=10 - +EVOLUTION_SPLITTING_SN_ECCENTRICITY_THRESHOLD=0.01 ############################## # WD kick distribution velocity dispersion @@ -2355,6 +2359,7 @@ $WARMUP \ --evolution_splitting $EVOLUTION_SPLITTING \ --evolution_splitting_sn_n $EVOLUTION_SPLITTING_SN_N \ --evolution_splitting_maxdepth $EVOLUTION_SPLITTING_MAXDEPTH \ +--evolution_splitting_sn_eccentricity_threshold $EVOLUTION_SPLITTING_SN_ECCENTRICITY_THRESHOLD \ --RLOF_angular_momentum_transfer_model $RLOF_ANGULAR_MOMENTUM_TRANSFER_MODEL \ --gravitational_radiation_model $GRAVITATIONAL_RADIATION_MODEL \ --gravitational_radiation_modulator_J $GRAVITATIONAL_RADIATION_MODULATOR_J \