From dbbae12819a7142782d16b60107d95636b315224 Mon Sep 17 00:00:00 2001 From: Robert Izzard <r.izzard@surrey.ac.uk> Date: Thu, 7 Nov 2019 14:41:59 +0000 Subject: [PATCH] add individual nova timestep acceleration --- src/binary_c_derivatives.h | 7 ++-- src/binary_c_parameters.h | 2 +- src/binary_c_structures.h | 7 ++++ ...ar_mass_and_angular_momentum_derivatives.c | 10 +++++ .../limit_accretion_rates.c | 24 ++++++++--- src/logging/log_every_timestep.c | 6 ++- src/perl/scripts2/template.pl | 2 +- src/perl/scripts2/yield_vs_time.pl | 6 +-- src/setup/cmd_line_args.h | 32 +++++++++++++- src/setup/set_default_preferences.c | 5 +++ src/timestep/timestep_limits.c | 42 ++++++++++++++++++- tbse | 35 ++++++++++++++++ 12 files changed, 160 insertions(+), 18 deletions(-) diff --git a/src/binary_c_derivatives.h b/src/binary_c_derivatives.h index 6987a8eb2..e801bd212 100644 --- a/src/binary_c_derivatives.h +++ b/src/binary_c_derivatives.h @@ -102,9 +102,9 @@ #define DERIVATIVE_STELLAR_NUM_THERMAL_PULSES_SINCE_MCMIN 41 #define DERIVATIVE_STELLAR_H_LAYER_MASS 42 #define DERIVATIVE_STELLAR_ROCHE_RADIUS 43 +#define DERIVATIVE_STELLAR_NUM_NOVAE 44 - -#define NUMBER_OF_STELLAR_DERIVATIVES 44 +#define NUMBER_OF_STELLAR_DERIVATIVES 45 #define STELLAR_DERIVATIVE_STRINGS \ { \ @@ -151,7 +151,8 @@ "Number of thermal pulses", \ "Number of thermal pulses since mcmin", \ "nova H layer mass", \ - "Roche radius" \ + "Roche radius", \ + "Number of novae" \ } #define Show_stellar_derivatives(S,SEPARATOR) \ diff --git a/src/binary_c_parameters.h b/src/binary_c_parameters.h index ef93466ad..2c67ee6d9 100644 --- a/src/binary_c_parameters.h +++ b/src/binary_c_parameters.h @@ -1690,7 +1690,7 @@ //#define TPAGBTRACKS /* log for Window To The Stars 2 */ -#define WTTS_LOG +//#define WTTS_LOG /* anti TZ project */ //#define ANTI_TZ diff --git a/src/binary_c_structures.h b/src/binary_c_structures.h index fe4f0c4c6..5a4552cf5 100644 --- a/src/binary_c_structures.h +++ b/src/binary_c_structures.h @@ -570,6 +570,10 @@ struct preferences_t { double beta_reverse_nova; double nova_irradiation_multiplier; double nova_faml_multiplier; + + double nova_timestep_accelerator_num; + double nova_timestep_accelerator_index; + double nova_timestep_accelerator_max; // gamma is the angular momentum factor for mass lost during Roche (-1.0) double rlof_angmom_gamma; // 0.0 @@ -1331,6 +1335,7 @@ struct star_t { double num_thermal_pulses; double num_thermal_pulses_since_mcmin; + double num_novae; double dntp; double menv_1tp; double Mc_prev_pulse; @@ -1741,6 +1746,8 @@ struct model_t { Boolean split_last_time; #endif // EVOLUTION_SPLITTING + + double nova_aggression_factor; }; struct orbit_t { diff --git a/src/binary_star_functions/apply_stellar_mass_and_angular_momentum_derivatives.c b/src/binary_star_functions/apply_stellar_mass_and_angular_momentum_derivatives.c index 7470fc2e7..130b5d288 100644 --- a/src/binary_star_functions/apply_stellar_mass_and_angular_momentum_derivatives.c +++ b/src/binary_star_functions/apply_stellar_mass_and_angular_momentum_derivatives.c @@ -251,7 +251,17 @@ void apply_stellar_mass_and_angular_momentum_derivatives(struct stardata_t * RES star->derivative, dt, DERIVATIVE_STELLAR_H_LAYER_MASS); + } + + /* + * Count novae + */ + apply_derivative(stardata, + &star->num_novae, + star->derivative, + dt, + DERIVATIVE_STELLAR_NUM_NOVAE); /* * Update the stellar type as a result of accretion: diff --git a/src/binary_star_functions/limit_accretion_rates.c b/src/binary_star_functions/limit_accretion_rates.c index 74041bfdf..c8ed7d296 100644 --- a/src/binary_star_functions/limit_accretion_rates.c +++ b/src/binary_star_functions/limit_accretion_rates.c @@ -336,7 +336,14 @@ void limit_accretion_rates(struct stardata_t * RESTRICT const stardata) 1.0 / (q*(1.0 + q)) / accretor->mass; - + /* + * Calculate the recurrence time, i.e. the time + * between successive nova explosions + */ + const double recurrence_time = + nova_recurrence_time(accretion_rate, + accretor->mass); + /* * Now we have calculated the properties of the * novae, decide whether we should model them @@ -372,7 +379,7 @@ void limit_accretion_rates(struct stardata_t * RESTRICT const stardata) * Increase the surface hydrogen layer mass. */ accretor->derivative[DERIVATIVE_STELLAR_H_LAYER_MASS] = accretion_rate; - + /* * Check if we have sufficient mass for explosion */ @@ -416,8 +423,7 @@ void limit_accretion_rates(struct stardata_t * RESTRICT const stardata) stardata->model.nova_timeout = stardata->model.time + NOVA_TIMEOUT_FACTOR * // usually 2 1e-6 * // convert yr to Myr - nova_recurrence_time(accretion_rate, - accretor->mass); + recurrence_time; } else { @@ -458,7 +464,15 @@ void limit_accretion_rates(struct stardata_t * RESTRICT const stardata) accretor->derivative[DERIVATIVE_STELLAR_MASS_NOVA]); } - + + + /* + * Count novae + */ + accretor->derivative[DERIVATIVE_STELLAR_NUM_NOVAE] = + 1.0 / recurrence_time; + + /* donor->derivative[DERIVATIVE_STELLAR_MASS_IRRADIATIVE_LOSS] = - 1.1e18 * (xi/4.0) * pow(1.0 + donor->mass,2.0/3.0) * pow(donor->mass,2.833) diff --git a/src/logging/log_every_timestep.c b/src/logging/log_every_timestep.c index 06628e436..8ed96f655 100644 --- a/src/logging/log_every_timestep.c +++ b/src/logging/log_every_timestep.c @@ -2177,7 +2177,7 @@ void log_every_timestep(struct stardata_t * RESTRICT const stardata) #ifdef LOG_INDIVIDUAL_NOVAE if(WHITE_DWARF(stardata->star[0].stellar_type)) { - printf("NOVAE %20.12e %20.12e %20.12e %20.12e %20.12e %20.12e %20.12e %20.12e %20.12e %u %u %d %20.12e %20.12e %20.12e %g %g %20.12e %d %d\n", + printf("NOVAE %20.12e %20.12e %20.12e %20.12e %20.12e %20.12e %20.12e %20.12e %20.12e %u %u %d %20.12e %20.12e %20.12e %g %g %20.12e %d %d %g %g\n", stardata->model.time,//1 stardata->star[0].mass, dt,//3 @@ -2197,7 +2197,9 @@ void log_every_timestep(struct stardata_t * RESTRICT const stardata) stardata->star[1].dmacc,//17 stardata->model.nova_timeout, //18 stardata->star[0].dtlimiter,//19 - stardata->star[1].dtlimiter //20 + stardata->star[1].dtlimiter, //20 + stardata->star[0].num_novae, //21 + stardata->star[1].num_novae //22 ); } #endif//LOG_INDIVIDUAL_NOVAE diff --git a/src/perl/scripts2/template.pl b/src/perl/scripts2/template.pl index 29e8a6073..0194e8883 100755 --- a/src/perl/scripts2/template.pl +++ b/src/perl/scripts2/template.pl @@ -123,7 +123,7 @@ if($duplicity == 0) { # make a grid of $nstars single binary stars, log-spaced, # with masses between $mmin and $mmax - my $nstars = 1000; + my $nstars = 10000; my $mmin = 0.1; my $mmax = 80.0; $population->add_grid_variable( diff --git a/src/perl/scripts2/yield_vs_time.pl b/src/perl/scripts2/yield_vs_time.pl index 61dd8ff85..11030e5a4 100755 --- a/src/perl/scripts2/yield_vs_time.pl +++ b/src/perl/scripts2/yield_vs_time.pl @@ -19,7 +19,7 @@ use Sys::Hostname; $|=1; # enable this line for auto-flushed output ############################################################ -# Version 2.1 for binary_c 2.1 +# Version 2.1.3 for binary_c 2.1.3 ############################################################ my $args = "@ARGV"; # used often @@ -28,7 +28,7 @@ my $hostname = hostname(); # output directory location my $voldisk = $ENV{VOLDISK} // $ENV{HOME}; my $outdir = ($args=~/outdir=(\S+)/)[0] // - $voldisk.'/data/pops/yields_vs_time-SNIa'; + $voldisk.'/data/pops/yields_vs_time-05112019'; print "Yield vs time : outdir=$outdir : voldisk=$voldisk, outdir=$outdir\n"; use vars qw($dt $logdt $tstart $logtimes $condor_count $differential $distribution $distribution_options $ensemble %ensemble_opts @ensemble_label $exacttimes $force $gnuplot $gridstring @isotopes $idt $nbins $nensemble $nisotopes $nensemble1 $nisotopes1 $norm_output $nsources $sources @source_label $version_string $yieldoutfile ); @@ -142,7 +142,7 @@ sub parser } else { - print "$header @$linearray\n"; + #print "$header @$linearray\n"; } # other output is ignored } diff --git a/src/setup/cmd_line_args.h b/src/setup/cmd_line_args.h index 3ddbd8dea..aa4fefd67 100644 --- a/src/setup/cmd_line_args.h +++ b/src/setup/cmd_line_args.h @@ -2994,7 +2994,7 @@ struct cmd_line_arg_t }, \ \ { \ - ARG_SECTION_OUTPUT, \ + ARG_SECTION_BINARY, \ "individual_novae", \ "If individual_novae is True, novae are resolved such that each explosion is performed separtaely.", \ ARG_BOOLEAN, \ @@ -3003,6 +3003,36 @@ struct cmd_line_arg_t 1.0 \ }, \ \ +{ \ + ARG_SECTION_BINARY, \ + "nova_timestep_accelerator_num", \ + "The nova timestep is accelerated if the nova number exceeds nova_timestep_accelerator_num. If zero or negative, acceleration is off. See also nova_timestep_accelerator_index and nova_timestep_accelerator_max.\n", \ + ARG_FLOAT, \ + WTTS_USE_DEFAULT, \ + &(stardata->preferences->nova_timestep_accelerator_num), \ + 1.0 \ + }, \ + \ +{ \ + ARG_SECTION_BINARY, \ + "nova_timestep_accelerator_index", \ + "The index at which the nova timestep is accelerated. A larger value gives longer timesteps. See also nova_timestep_accelerator_num and nova_timestep_accelerator_max.\n", \ + ARG_FLOAT, \ + WTTS_USE_DEFAULT, \ + &(stardata->preferences->nova_timestep_accelerator_index), \ + 1.0 \ + }, \ + \ +{ \ + ARG_SECTION_BINARY, \ + "nova_timestep_accelerator_max", \ + "The nova timestep is accelerated by a factor that is capped at nova_timestep_accelerator_max. This parameter is ignored if it is zero or negative. See also nova_timestep_accelerator_num and nova_timestep_accelerator_index.\n", \ + ARG_FLOAT, \ + WTTS_USE_DEFAULT, \ + &(stardata->preferences->nova_timestep_accelerator_max), \ + 1.0 \ + }, \ + \ { \ ARG_SECTION_OUTPUT, \ "force_corotation_on_RLOF", \ diff --git a/src/setup/set_default_preferences.c b/src/setup/set_default_preferences.c index 9daf72989..d4ff10033 100644 --- a/src/setup/set_default_preferences.c +++ b/src/setup/set_default_preferences.c @@ -87,6 +87,11 @@ void set_default_preferences(struct preferences_t * RESTRICT const preferences) preferences->donor_limit_thermal_multiplier=DONOR_LIMIT_THERMAL_MULTIPLIER_DEFAULT; preferences->donor_limit_dynamical_multiplier=DONOR_LIMIT_DYNAMICAL_MULTIPLIER_DEFAULT; preferences->donor_limit_dynamical_multiplier=DONOR_LIMIT_ENVELOPE_MULTIPLIER_DEFAULT; + + /* nova timestep accelerators */ + preferences->nova_timestep_accelerator_num = 100; + preferences->nova_timestep_accelerator_max = -1.0; + preferences->nova_timestep_accelerator_index = 0.5; preferences->rlof_angmom_gamma=NONCONSERVATIVE_ANGMOM_GAMMA_DEFAULT; preferences->nonconservative_angmom_gamma=NONCONSERVATIVE_ANGMOM_GAMMA_DEFAULT; diff --git a/src/timestep/timestep_limits.c b/src/timestep/timestep_limits.c index 1848c2537..e394f72ec 100644 --- a/src/timestep/timestep_limits.c +++ b/src/timestep/timestep_limits.c @@ -283,14 +283,52 @@ void timestep_limits(Timestep_prototype_args) stardata->preferences->timestep_multipliers[DT_LIMIT_NOVAE] * dtnova; + /* + * Modulate to combine multiple novae + * + * The factor f is applied only if we have already had more than + * nova_timestep_accelerator_num novae. + * + * If accelerator_num <= 0, f = 1.0. + * + * If Nnovae < accelerator_num, f = 1.0. + * + * Then, if acclerator_max > 0.0 we have: + * + * f = Max(accelerator_max, pow(Nnovae, accelerator_index)) + * + * otherwise + * + * f = pow(Nnovae, accelerator_index). + */ + const double f = + + stardata->preferences->nova_timestep_accelerator_num < +TINY ? + /* num < 0.0 : f = 1.0 */ + 1.0 : + ( + /* the cap is LARGE_FLOAT (i.e. very large) if acclerator_max <= 0.0 */ + Max( + (stardata->preferences->nova_timestep_accelerator_max < +TINY ? + LARGE_FLOAT : + stardata->preferences->nova_timestep_accelerator_max), + + /* check we've had sufficient novae */ + (star->num_novae > stardata->preferences->nova_timestep_accelerator_num ? + /* apply the pow(Nnovae, index) */ + pow(star->num_novae,stardata->preferences->nova_timestep_accelerator_index) : + /* or don't */ + 1.0) + ) + ); + /* * limit timestep because of novae */ Limit_timestep(*dt, - dtlim, + dtlim*f, star, DT_LIMIT_NOVAE); - } if(star->starnum == 0) diff --git a/tbse b/tbse index ce154f496..351de6b6b 100755 --- a/tbse +++ b/tbse @@ -1181,6 +1181,37 @@ TIMESTEP_SOLVER_FACTOR=1.0 # global timestep modulator for non-remnants (1.0) TIMESTEP_MODULATOR=1.0 +############################################################ +# Nova timestep acceleration. +# +# The idea here +# +# The factor f is applied only if we have already had more than +# nova_timestep_accelerator_num novae. +# +# If accelerator_num <= 0, f = 1.0 (i.e. no acceleration). +# +# If Nnovae < accelerator_num, f = 1.0 (i.e. no acceleration). +# +# Then, if acclerator_max > 0.0 we use, +# +# f = Max(accelerator_max, pow(Nnovae, accelerator_index)) +# +# otherwise +# +# f = pow(Nnovae, accelerator_index). +# +# Typically, num=100, index=0.5 and max=-1 works well. +# +# Note that max=-1 does not mean the timestep will be necessarily +# large: there are many other limits that can (and do) apply (see +# below). +# +############################################################ +NOVA_TIMESTEP_ACCELERATOR_NUM=100 # 100 +NOVA_TIMESTEP_ACCELERATOR_INDEX=0.5 # 0.5 +NOVA_TIMESTEP_ACCELERATOR_MAX=-1 # -1 + ############################################################ # Individual by-process timestep multipliers # @@ -2142,6 +2173,10 @@ $TIMESTEP_MULTIPLIERS \ --overspin_algorithm $OVERSPIN_ALGORITHM \ --gaia_Teff_binwidth $GAIA_TEFF_BINWIDTH \ --gaia_L_binwidth $GAIA_L_BINWIDTH \ +--nova_timestep_accelerator_num $NOVA_TIMESTEP_ACCELERATOR_NUM \ +--nova_timestep_accelerator_index $NOVA_TIMESTEP_ACCELERATOR_INDEX \ +--nova_timestep_accelerator_max $NOVA_TIMESTEP_ACCELERATOR_MAX \ + "; # valgrind options -- GitLab