diff --git a/src/binary_c_macros.h b/src/binary_c_macros.h index c24b6d2d1c2041cc70a4564a0ec24ca4a7f27183..2eb41d9d4a8e7e8fb0fdad92394501a66ef3004f 100644 --- a/src/binary_c_macros.h +++ b/src/binary_c_macros.h @@ -837,18 +837,23 @@ } +/* + * Nova states + */ #define NOVA_STATE_NONE 0 -#define NOVA_STATE_TRIGGER 1 -#define NOVA_STATE_POST 2 +#define NOVA_STATE_PRE_EXPLOSION 1 +#define NOVA_STATE_EXPLODING 2 #define NOVA_STATE_QUIESCENT 3 #define NOVA_STATE_STRINGS { \ "None", \ - "Triggered", \ - "Post-nova", \ + "Pre-explosion", \ + "Exploding", \ "Quiescent" \ } - +/* + * TPAGB luminosity algorithm + */ #define TPAGB_LUMINOSITY_AVERAGE 0 #define TPAGB_LUMINOSITY_DIPS 1 diff --git a/src/binary_c_parameters.h b/src/binary_c_parameters.h index 634e1c7b2aff255a0576cc14170c9160b6baf85f..5e7d96474a5d4c9cbdbe2abf331343ceed453237 100644 --- a/src/binary_c_parameters.h +++ b/src/binary_c_parameters.h @@ -720,6 +720,12 @@ /* deprecated: instant mixing on the companion */ //#define NOVA_BACK_ACCRETION_INSTANT_MIXING +/* + * after a nova explosion, we continue short timesteps + * until NOVA_TIMEOUT_FACTOR * nova_recurrance_time + */ +#define NOVA_TIMEOUT_FACTOR 2.0 + /************************************************************ * Mass transfer by stellar winds ************************************************************/ diff --git a/src/binary_c_structures.h b/src/binary_c_structures.h index 21057d23ca6a8308bd5b3835439fc5fae0255566..28e553a382964290646a5792ceb6d9d22ea6f035 100644 --- a/src/binary_c_structures.h +++ b/src/binary_c_structures.h @@ -1054,10 +1054,10 @@ struct diffstats_t double orbital_eccentricity; double orbital_angular_frequency; double novarate[NUMBER_OF_STARS],v_eq_ratio[NUMBER_OF_STARS]; - int novastate[NUMBER_OF_STARS]; - double time; + Time time; Stellar_type stellar_type[NUMBER_OF_STARS],hybrid_HeCOWD[NUMBER_OF_STARS]; Supernova_type SN_type[NUMBER_OF_STARS]; + Nova_type nova[NUMBER_OF_STARS]; Boolean sgl,artificial_accretion; }; @@ -1359,9 +1359,7 @@ struct star_t { double interpulse_period; double mc_1tp; /* core mass at first pulse */ double lambda_3dup; - double time_prev_nova,time_next_nova,dtnova; - - double dm_novaH,nova_timeout; + double dm_novaH; double nova_beta,nova_faml; #ifdef RUNAWAY_STARS @@ -1503,7 +1501,6 @@ struct star_t { Stellar_type stellar_type; /* stellar type */ Stellar_type detached_stellar_type; /* stellar type when detached */ Star_number starnum; // set to 0 for primary, 1 for secondary. useful for logging - int novastate; #ifdef DISCS int ndiscs; @@ -1534,6 +1531,7 @@ struct star_t { Reject_index reject; Stellar_type compact_core_type; + Nova_state nova; Boolean hybrid_HeCOWD; #ifdef WD_KICKS @@ -1543,7 +1541,7 @@ struct star_t { #ifdef LOG_SUPERNOVAE Boolean supernova; #endif//LOG_SUPERNOAVE - Boolean nova; + #ifdef NUCSYN Boolean rstar; /* true if star is R type */ Boolean first_dredge_up; /* stores whether we've had first dredge up */ @@ -1632,7 +1630,7 @@ struct model_t { double time; /* the time, was tphys in the fortran version */ double max_evolution_time; /* Maximum evolution time, in Myr */ double dt,dtm,true_dtm,time_remaining,dtmwas; /* timestepping */ - double dt_zoomfac,RLOF_recommended_timestep; + double dt_zoomfac,RLOF_recommended_timestep,nova_timeout; double prev_log_t; #ifdef FABIAN_IMF_LOG double next_fabian_imf_log_time; diff --git a/src/binary_c_types.h b/src/binary_c_types.h index a0cdbecac0d4c03de9b9971b55e0e60cfae9a735..6134ca5d347f3128383f88e15dceec57ca60d42f 100644 --- a/src/binary_c_types.h +++ b/src/binary_c_types.h @@ -123,6 +123,7 @@ typedef unsigned int Boolean; #define Spectral_type __int__ #define Long_spectral_type __double__ #define Nova_type __unsigned__ __int__ +#define Nova_state __unsigned__ __int__ #define Reaction_network __unsigned__ __int__ #ifdef CODESTATS diff --git a/src/binary_star_functions/limit_accretion_rates.c b/src/binary_star_functions/limit_accretion_rates.c index eadbe7c992748068e8a0a38cd679d3a4617275fe..74041bfdf03bb103fc2d9f5023d545514e2dcf8d 100644 --- a/src/binary_star_functions/limit_accretion_rates.c +++ b/src/binary_star_functions/limit_accretion_rates.c @@ -20,8 +20,7 @@ void limit_accretion_rates(struct stardata_t * RESTRICT const stardata) { struct star_t * accretor = &stardata->star[k]; struct star_t * donor = &stardata->star[Other_star(k)]; - accretor->nova = FALSE; - + Dprint("limit acc rate star %d : is currently %g\n", k, Mdot_net(accretor)); @@ -240,7 +239,6 @@ void limit_accretion_rates(struct stardata_t * RESTRICT const stardata) { steady_burn_rate = steady_burn_rate_He; nova_type = NOVA_TYPE_HELIUM; - accretor->nova = TRUE; } /* restore stellar type */ @@ -337,6 +335,14 @@ void limit_accretion_rates(struct stardata_t * RESTRICT const stardata) Pythag2(vrat,1.0) * geometric_accretion_fraction * 1.0 / (q*(1.0 + q)) / accretor->mass; + + + /* + * Now we have calculated the properties of the + * novae, decide whether we should model them + * individually (with short timesteps), or in an + * average way (with long timesteps). + */ if(stardata->preferences->individual_novae == TRUE) { /* @@ -382,7 +388,7 @@ void limit_accretion_rates(struct stardata_t * RESTRICT const stardata) new_nova->accretion_rate = accretion_rate; new_nova->steady_burn_rate = steady_burn_rate; new_nova->f = f; - accretor->nova = TRUE; + accretor->nova = NOVA_STATE_EXPLODING; if(Add_new_event(stardata, BINARY_C_EVENT_NOVA, &nova_event_handler, @@ -403,95 +409,34 @@ void limit_accretion_rates(struct stardata_t * RESTRICT const stardata) */ Safe_free(new_nova); } - } -#ifdef __DEPRECATED - /* - * The following code was for before we used - * the events framework for individiual novae. - */ - - /* - * Check if we have sufficient mass for explosion - */ - if(accretor->dm_novaH > dMcrit) - { + /* - * Nova explosion : - * - * In theory, we should burn dMcrit of material. - * However, there is likely a bit more than dMcrit - * in the layer. We burn it all to maintain mass - * conservation. + * If we're exploding now, set the next timeout */ - accretor->nova = TRUE; - if(accretor->novastate == NOVA_STATE_TRIGGER) - { - /* - * A nova has been triggered. - * - * The timestep is short. - * - * Calculate dm_lost, the mass lost from - * the white dwarf in the nova explosion, - * hence the nova mass loss rate. - */ - - const double dm_lost = (1.0-f) * accretor->dm_novaH; - const double dm_loss_rate = - dm_lost / stardata->model.dt; - accretor->derivative[DERIVATIVE_STELLAR_MASS_NOVA] += - dm_loss_rate; - - Dprint("remove %g from M=%g (f = %g) at rate %g with dt %g \n", - dm_lost, - accretor->mass, - f, - accretor->derivative[DERIVATIVE_STELLAR_MASS_NOVA], - stardata->model.dt - ); - - /* - * Remove all the accreted layer : anything - * remaining becomes part of the white dwarf. - */ - accretor->derivative[DERIVATIVE_STELLAR_H_LAYER_MASS] += - dm_loss_rate; - - /* - * Trigger complete, change novastate state - * to NOVA_STATE_POST which enforces another - * short timestep with no nova. - */ - accretor->novastate = NOVA_STATE_POST; - } - else - { - /* - * trigger a nova on next (short) timestep - */ - accretor->novastate = NOVA_STATE_TRIGGER; - } + 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); } -#endif // __DEPRECATED (was INDIVIDUAL_NOVAE_EVENTS) - else { /* * Phase between novae. * * If there has been a previous nova explosion, i.e. - * novastate is not NOVA_STATE_NONE (it is likely - * NOVA_STATE_POST), then we set NOVA_STATE_QUIESCENT. + * accretor->nova is not NOVA_STATE_NONE, + * then we set accretor->nova to NOVA_STATE_QUIESCENT. * - * If there has never been a nova, stick to - * the current state which must be NOVA_STATE_NONE. + * If there has not yet been a nova, but we expect one + * soon, set to NOVA_STATE_PRE_EXPLOSION. */ accretor->derivative[DERIVATIVE_STELLAR_MASS_NOVA] = 0.0; - - if(accretor->novastate != NOVA_STATE_NONE) - { - accretor->nova = TRUE; - accretor->novastate = NOVA_STATE_QUIESCENT; - } + accretor->nova = + (accretor->nova == NOVA_STATE_QUIESCENT || + accretor->nova == NOVA_STATE_EXPLODING) ? + NOVA_STATE_QUIESCENT : + NOVA_STATE_PRE_EXPLOSION; } } else @@ -499,11 +444,15 @@ void limit_accretion_rates(struct stardata_t * RESTRICT const stardata) /* * Novae are modelled as average events, which are put in - * the normal mass loss + * the normal mass loss. + * + * We set nova to be NOVA_STATE_EXPLODING on the assumption + * that the timestep is long so there are going to be some + * explosions, but it's not really relevant. */ accretor->derivative[DERIVATIVE_STELLAR_MASS_NOVA] += - (1.0-f) * accretion_rate; - accretor->nova = TRUE; + accretor->nova = NOVA_STATE_EXPLODING; Dprint("accretion rate %g -> dM/dt nova = %g\n", accretion_rate, accretor->derivative[DERIVATIVE_STELLAR_MASS_NOVA]); @@ -531,11 +480,10 @@ void limit_accretion_rates(struct stardata_t * RESTRICT const stardata) donor->derivative[DERIVATIVE_STELLAR_MASS_NOVA] += accretor->nova_beta * -accretor->derivative[DERIVATIVE_STELLAR_MASS_NOVA]; } - else { /* - * We have steady initial burning. + * We have steady burning. * * Accretion rate exceeds the steady burning rate * either burning is steady, or the star forms @@ -544,9 +492,9 @@ void limit_accretion_rates(struct stardata_t * RESTRICT const stardata) * Note: we do not treat the case where * there is steady accretion of hydrogen, but then * helium flashes underneath which would leave to - * helium novae. These should be caught here. + * helium novae. These should be caught here (todo!). */ - accretor->novastate = NOVA_STATE_NONE; + accretor->nova = NOVA_STATE_NONE; if(accretion_rate < new_envelope_rate) { @@ -569,6 +517,7 @@ void limit_accretion_rates(struct stardata_t * RESTRICT const stardata) /* * Accretion onto a neutron star/black hole, what to do? */ + accretor->nova = NOVA_STATE_NONE; } } else @@ -576,46 +525,29 @@ void limit_accretion_rates(struct stardata_t * RESTRICT const stardata) /* * No longer a compact object : cannot have novae */ - accretor->novastate = NOVA_STATE_NONE; + accretor->nova = NOVA_STATE_NONE; } } // accretion rate > 0 check else { /* - * We may have had novae, but are no longer transferring mass. - * In this case, force the NOVA_STATE_QUIESCENT to prevent - * the timestep remaining very short. + * Accretion rate is zero or negative, i.e. mass + * is constant or being lost. */ - accretor->novastate = - accretor->novastate == NOVA_STATE_NONE ? - NOVA_STATE_NONE : NOVA_STATE_QUIESCENT; - - if((accretor->novastate == NOVA_STATE_QUIESCENT || - Is_not_zero(accretor->derivative[DERIVATIVE_STELLAR_MASS_NOVA])) && - (Is_not_zero(accretor->nova_timeout) && stardata->model.time > accretor->nova_timeout)) - { - accretor->nova = TRUE; - } + + + /* + * If we were previously having novae, keep the state + * at NOVA_STATE_QUIESCENT until nova_timeout has been reached + */ + accretor->nova = + ( + accretor->nova == NOVA_STATE_QUIESCENT || + accretor->nova == NOVA_STATE_EXPLODING || + stardata->model.time < stardata->model.nova_timeout + ) + ? NOVA_STATE_QUIESCENT : NOVA_STATE_NONE; } - } + } } -/* - static Pure_function double MM93_k(const double m1, - const double m2, - const double xL) - { - return sqrt( - ( - m1/Pow3(xL) + - m2/Pow3(1.0-xL) + - -1.0 - ) - * - ( - m1/Pow3(xL) + - m2/Pow3(1.0-xL) - ) - ); - } -*/ diff --git a/src/evolution/evolution_difflog.c b/src/evolution/evolution_difflog.c index 3b605207ea7da2920cecf7643b9d03325705a76c..951a6d04c4c8e531f0d9e8a4d0b9b8a6324ffda4 100644 --- a/src/evolution/evolution_difflog.c +++ b/src/evolution/evolution_difflog.c @@ -385,7 +385,7 @@ static void set_diffstats(struct stardata_t * stardata, now->accretion_luminosity[k] = star->accretion_luminosity; now->luminosity[k] = star->luminosity; now->novarate[k] = star->derivative[DERIVATIVE_STELLAR_MASS_NOVA]; - now->novastate[k] = star->nova; + now->nova[k] = star->nova; now->v_eq_ratio[k] = star->v_eq_ratio; now->SN_type[k] = star->SN_type; now->artificial_accretion = @@ -471,12 +471,26 @@ static void cf_diffstats(struct stardata_t * RESTRICT const stardata, } /* novae */ - if(now->sgl == FALSE) { const Boolean novae = - stardata->preferences->individual_novae == TRUE ? - Boolean_(now->novastate[k] == TRUE) : - Boolean_(now->novarate[k] < 0.0); + now->sgl == TRUE ? FALSE : + ( + stardata->preferences->individual_novae == TRUE ? + + /* + * indiviudal novae algorithm: + * Novae are happening when there has been at least + * one explosion + */ + Boolean_(now->nova[k] == NOVA_STATE_EXPLODING || + now->nova[k] == NOVA_STATE_QUIESCENT) : + /* + * time-averaged novae (like BSE): + * Novae are happening when the nova mass derivative is + * negative (i.e. mass is being lost, on average). + */ + Boolean_(now->novarate[k] < 0.0) + ); if((novae == TRUE) && lockflags[k][LOCK_NOVAE] == FALSE) @@ -490,7 +504,6 @@ static void cf_diffstats(struct stardata_t * RESTRICT const stardata, lockflags[k][LOCK_NOVAE] = FALSE; flags[END_NOVAE_LABEL] = TRUE; } - } /* AGB star shrinkage */ @@ -636,7 +649,6 @@ static void cf_diffstats(struct stardata_t * RESTRICT const stardata, stardata->common.Xsolar, stardata); CEMP = Boolean_(CFe > 1.0); - } else { diff --git a/src/evolution/evolution_rejection_tests.c b/src/evolution/evolution_rejection_tests.c index ceef3abe4cc95dc6284a6e00a6b1b08ecc7012a1..b30aa8b429cf028ab8ff2fb2ffa423e84b7810b5 100644 --- a/src/evolution/evolution_rejection_tests.c +++ b/src/evolution/evolution_rejection_tests.c @@ -1,6 +1,6 @@ #include "../binary_c.h" static Boolean smooth_evolution(struct stardata_t * stardata); -static Boolean smooth_evolution_checker( +static Boolean MAYBE_UNUSED smooth_evolution_checker( struct stardata_t * stardata, const Boolean check_stellar_type_change, const Boolean check_duplicity_change, diff --git a/src/evolution/init_star.c b/src/evolution/init_star.c index 47f185f036372cf455aee29202d3b06717005588..64ffb07d4cad4f9601f4ce18e0a4de2b95e5be1b 100644 --- a/src/evolution/init_star.c +++ b/src/evolution/init_star.c @@ -34,7 +34,7 @@ void init_star(struct stardata_t * const stardata, star->max_mix_depth=1e3; #endif /* NUCSYN */ - star->stellar_type=MAIN_SEQUENCE; - + star->stellar_type = MAIN_SEQUENCE; + star->nova = NOVA_STATE_NONE; Dprint("Done for this star\n"); } diff --git a/src/logging/log_every_timestep.c b/src/logging/log_every_timestep.c index dfee32b1ccedbfb771aa93c40d899b833f3ae5ef..1998ffe72d20628289c4e381c72601702d2f8737 100644 --- a/src/logging/log_every_timestep.c +++ b/src/logging/log_every_timestep.c @@ -2188,25 +2188,31 @@ void log_every_timestep(struct stardata_t * RESTRICT const stardata) stardata->common.orbit.separation); */ +#define LOG_INDIVIDUAL_NOVAE #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 %d %20.12e %20.12e %20.12e %g %g\n", - stardata->model.time, + 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", + stardata->model.time,//1 stardata->star[0].mass, - dt, + dt,//3 stardata->star[1].radius / stardata->star[1].roche_radius, stardata->star[1].mass,//5 stardata->star[1].radius, Mdot_net(&stardata->star[1]), stardata->star[0].dm_novaH, //8 stardata->star[0].derivative[DERIVATIVE_STELLAR_MASS_NOVA], - (stardata->star[0].nova || stardata->star[1].nova) ? 1 : 0, //10 - Mdot_net(&stardata->star[0]), //11 accretor rate (+ve when accreting, -ve when exploding) - Mdot_net(&stardata->star[1]), //12 donor rate (-ve) - stardata->common.orbit.separation, //13 - stardata->star[0].dmacc, - stardata->star[1].dmacc + stardata->star[0].nova,//10 + stardata->star[1].nova, + (stardata->star[0].nova || stardata->star[1].nova) ? 1 : 0, //12 + Mdot_net(&stardata->star[0]), //13 accretor rate (+ve when accreting, -ve when exploding) + Mdot_net(&stardata->star[1]), //14 donor rate (-ve) + stardata->common.orbit.separation, //15 + stardata->star[0].dmacc,//16 + stardata->star[1].dmacc,//17 + stardata->model.nova_timeout, //18 + stardata->star[0].dtlimiter,//19 + stardata->star[1].dtlimiter //20 ); } #endif//LOG_INDIVIDUAL_NOVAE @@ -2667,5 +2673,4 @@ void log_every_timestep(struct stardata_t * RESTRICT const stardata) } } #endif//GAIAHRD - } diff --git a/src/novae/nova_event_handler.c b/src/novae/nova_event_handler.c index a595dfce1aef3c54d935e6a12b9cfbcf6df76cce..2ca4ad3ae911580a716bf170af0bff0688555874 100644 --- a/src/novae/nova_event_handler.c +++ b/src/novae/nova_event_handler.c @@ -68,7 +68,6 @@ Event_handler_function nova_event_handler(void * const eventp, exploder->dm_novaH = 0.0; exploder->dmacc = 0.0; exploder->mass -= dm_lost; - exploder->novastate = NOVA_STATE_POST; #ifdef NUCSYN /* @@ -109,10 +108,24 @@ Event_handler_function nova_event_handler(void * const eventp, donor->dmacc += dm_gain; #ifdef NUCSYN + /* + * Put accreted material into the star's accretion layer + */ nucsyn_dilute_shell( - donor->dmacc,donor->Xacc, - dm_gain,Xnova + donor->dmacc, + donor->Xacc, + dm_gain, + Xnova ); + + /* + * Perhaps mix the star's accretion layer into its envelope + */ + if(nucsyn_thermohaline_unstable(stardata,donor)) + { + nucsyn_thermohaline_mix_star(stardata, + donor); + } /* * "negative-yield" accreted material diff --git a/src/nucsyn/nucsyn_prototypes.h b/src/nucsyn/nucsyn_prototypes.h index a1a9f82a44916e8a5632b03091dc05167c20081f..9b4cab799f03a4c60ec5959bd226525220467d3d 100644 --- a/src/nucsyn/nucsyn_prototypes.h +++ b/src/nucsyn/nucsyn_prototypes.h @@ -268,11 +268,11 @@ double Pure_function Nonnull_some_arguments(1,2) XXsum(const struct stardata_t * #ifdef NUCSYN_THERMOHALINE_MIXING_TIME Constant_function double nucsyn_thermohaline_mixing_time(const double mu0, - const double mu1, - const double dmacc, - const double m, - const double l, - const double r); + const double mu1, + const double dmacc, + const double m, + const double l, + const double r); #endif void nucsyn_set_nova_abunds(struct stardata_t * const stardata, @@ -475,11 +475,10 @@ double Constant_function nucsyn_CN_timescale(const double t9, void nucsyn_thermohaline_mix(struct stardata_t * const stardata, const Star_number k, // accreting star number - const Abundance * const Xacc, // accretion abundances + Abundance * const Xacc, // accretion abundances const double dmacc, // mass accreted const Abundance * const Xenv, // envelope abundances: pre mix - Abundance * const nXenv, // envelope abundances: post mix (written) - const double mforce // force mixing down to this co-ordinate + Abundance * const nXenv // envelope abundances: post mix (written) ); void nucsyn_set_sigmav_from_table(struct stardata_t * const stardata, @@ -634,6 +633,13 @@ void nucsyn_remove_mass_from_surface( double * RESTRICT ndmacc, Boolean *RESTRICT allocated); + + +Boolean nucsyn_thermohaline_unstable(struct stardata_t * const stardata, + struct star_t * const star); + +void nucsyn_thermohaline_mix_star(struct stardata_t * const stardata, + struct star_t * const star); #endif /* NUCSYN */ #endif /* NUCSYN_PROTOYPES */ diff --git a/src/nucsyn/nucsyn_thermohaline_mix.c b/src/nucsyn/nucsyn_thermohaline_mix.c index 759ae606a4e7d82322b1ae1383b9d8a4946c4c0f..326fb8f6ee2f7d1b3d5df95b8d6e34df686f7f1f 100644 --- a/src/nucsyn/nucsyn_thermohaline_mix.c +++ b/src/nucsyn/nucsyn_thermohaline_mix.c @@ -2,13 +2,12 @@ #include "nucsyn.h" #ifdef NUCSYN -void nucsyn_thermohaline_mix(struct stardata_t * stardata, +void nucsyn_thermohaline_mix(struct stardata_t * const stardata, const Star_number k, // accreting star number - const Abundance * const Xacc, // accretion abundances + Abundance * const Xacc, // accretion abundances const double dmacc, // mass accreted const Abundance * const Xenv, // envelope abundances: pre mix - Abundance * const nXenv, // envelope abundances: post mix (written) - const double mforce // force mixing down to this co-ordinate + Abundance * const nXenv // envelope abundances: post mix (written) ) { SETstar(k); // the accreting star @@ -27,21 +26,36 @@ void nucsyn_thermohaline_mix(struct stardata_t * stardata, #endif//MIXDEBUG /* Accretion layer sinks */ - double menv = nucsyn_envelope_mass(&stardata->star[k]); + const double menv = nucsyn_envelope_mass(&stardata->star[k]); Dprint("menv = %g, dmacc = %g\n",menv,dmacc); /* Fully mix accretion layer with envelope */ - nucsyn_dilute_shell_to( - /* Accretion layer... */ - dmacc, - Xacc, - /* envelope ... */ - menv, - Xenv, - /* New envelope */ - nXenv); + if(likely(Xenv != nXenv)) + { + nucsyn_dilute_shell_to( + /* Accretion layer... */ + dmacc, + Xacc, + /* envelope ... */ + menv, + Xenv, + /* New envelope */ + nXenv); + } + else + { + nucsyn_dilute_shell( + /* Accretion layer... */ + dmacc, + Xacc, + /* envelope ... */ + menv, + Xenv + ); + } + if(ON_MAIN_SEQUENCE(star->stellar_type)) { /* diff --git a/src/nucsyn/nucsyn_thermohaline_mix_star.c b/src/nucsyn/nucsyn_thermohaline_mix_star.c new file mode 100644 index 0000000000000000000000000000000000000000..42895d6781deb4043531987cbbedb2195341d77b --- /dev/null +++ b/src/nucsyn/nucsyn_thermohaline_mix_star.c @@ -0,0 +1,21 @@ +#include "../binary_c.h" + +#ifdef NUCSYN + +/* + * Wrapper for nucsyn_thermohaline_mix to mix a star + * given in the star struct + */ + +void nucsyn_thermohaline_mix_star(struct stardata_t * const stardata, + struct star_t * const star) +{ + nucsyn_thermohaline_mix(stardata, + star->starnum, + star->Xacc, + star->dmacc, + star->Xenv, + star->Xenv); +} + +#endif diff --git a/src/nucsyn/nucsyn_thermohaline_unstable.c b/src/nucsyn/nucsyn_thermohaline_unstable.c new file mode 100644 index 0000000000000000000000000000000000000000..ff133dca522c7509db001654aa61b598d5140f13 --- /dev/null +++ b/src/nucsyn/nucsyn_thermohaline_unstable.c @@ -0,0 +1,31 @@ +#include "../binary_c.h" + +#ifdef NUCSYN + +/* + * Function to return TRUE if the star's current accretion layer + * has a higher molecular weight than the material below it, + * and hence is thermohaline unstable. + * + * Note: we assume an ionisation fraction of 100%. + */ + +Boolean nucsyn_thermohaline_unstable(struct stardata_t * const stardata, + struct star_t * const star) +{ + + const double mu_acc = nucsyn_molecular_weight(star->Xacc, + stardata, + 1.0); + const double mu_env = nucsyn_molecular_weight(star->Xenv, + stardata, + 1.0); + + return mu_acc > mu_env ? TRUE : FALSE; +} + + +#endif + + + diff --git a/src/nucsyn/nucsyn_update_abundances.c b/src/nucsyn/nucsyn_update_abundances.c index 717a590adbaedf5c9313119408fcf518edd3db4f..e41c273f5915e42e974f432507f0a1cf1eda956f 100644 --- a/src/nucsyn/nucsyn_update_abundances.c +++ b/src/nucsyn/nucsyn_update_abundances.c @@ -1,8 +1,10 @@ #include "../binary_c.h" /* - * Function to update the abundance of each star due to mass - * mass transfer, gain and loss + * Subroutine to update the abundance of each star due to mass + * mass transfer, gain and loss. + * + * This subroutine */ #ifdef NUCSYN @@ -500,8 +502,8 @@ void Hot_function nucsyn_update_abundances(struct stardata_t * RESTRICT const st nXacc[k], ndmacc[k], Xenv[k], - nXenv[k], - -1.0); + nXenv[k]); + ndmacc[k] = 0.0; MDEBUG("\nafter mix C12 : acc %g env %g ", diff --git a/src/timestep/timestep_limits.c b/src/timestep/timestep_limits.c index 26c9f38e61c9ba49d5183377794df6d64c523780..1848c2537aa8f517e10d0f4f084d1d7c9eb7f171 100644 --- a/src/timestep/timestep_limits.c +++ b/src/timestep/timestep_limits.c @@ -257,126 +257,40 @@ void timestep_limits(Timestep_prototype_args) } - if(stardata->preferences->individual_novae == TRUE) + if(stardata->preferences->individual_novae == TRUE && + WHITE_DWARF(star->stellar_type) && + (star->nova != NOVA_STATE_NONE || + stardata->model.time < stardata->model.nova_timeout)) { - if(WHITE_DWARF(star->stellar_type)) - { - const double accretion_rate = Mdot_gain(star); - if(Is_zero(star->time_next_nova)) - { - /* first time setup */ - star->time_next_nova = stardata->model.time; - star->time_prev_nova = stardata->model.time; - } - if(star->nova == TRUE) - { - /* - * When novae are switched on and off because the system - * becomes occasionally detached it's hard to know - * dtnova (because mdot is sometimes zero). - * - * If dtnova is zero, this is the first time, then assume - * a mass transfer rate of 1e-9 Msun/yr if nothing else. - */ - - double dtlim; - - if(Is_zero(star->dtnova)) - { - star->dtnova = nova_recurrence_time(1e-9, - star->mass); - } - -#ifdef __DEPRECATED - if(star->novastate == NOVA_STATE_TRIGGER) - { - /* - * Nova triggered: short timestep - * required - */ - dtlim = stardata->preferences->minimum_timestep; - star->dtnova = nova_recurrence_time(accretion_rate, - star->mass); - - /* - * Keep the nova state either when accreting or - * until after nova_timeout: this keeps the timestep - * short enough to resolve novae for a while, just in case - * they restart. - */ - star->nova_timeout = stardata->model.time + 3.0 * star->dtnova; - } - else if(star->novastate == NOVA_STATE_POST) - { - /* - * Just after nova: also a short timsetep - */ - dtlim = stardata->preferences->minimum_timestep; - } - else - { - /* - * We have between nova explosions, try - * to resolve them - */ - dtlim = stardata->preferences->timestep_multipliers[DT_LIMIT_NOVAE] * star->dtnova; - } -#endif - - star->dtnova = nova_recurrence_time(accretion_rate, + /* + * When novae are switched on and off because the system + * becomes occasionally detached it's hard to know + * dtnova (because mdot is sometimes zero). + * + * If dtnova is zero, this is the first time, then assume + * a mass transfer rate of 1e-9 Msun/yr if nothing else. + */ + const double accretion_rate = Mdot_gain(star); + const Time dtnova = 1e-6 * nova_recurrence_time(accretion_rate, star->mass); - dtlim = stardata->preferences->timestep_multipliers[DT_LIMIT_NOVAE] * star->dtnova; - - dtlim *= 1e-6; // convert to Myr - - /* - * limit timestep because of novae - */ - Limit_timestep(*dt, - dtlim, - star, - DT_LIMIT_NOVAE); - } - else - { - /* dtnova is in YEARS, */ - double dtnova = nova_recurrence_time(accretion_rate, - star->mass); - - if(0) - printf("TIME RES NOVAE : dtnova = %g from M=%g, accretion rate %g (net %g)\n", - dtnova, - star->mass, - accretion_rate, - Mdot_net(star) - ); - if(More_or_equal(stardata->model.time, - star->time_next_nova)) - { - /* - printf("NOVANOVANOVA at %g (prev at %g, next at %g, dtnova(M=%g,Mdot=%g)=%g Myr)\n", - stardata->model.time, - star->time_prev_nova, - star->time_prev_nova + dtnova*1e-6, - star->mass, - accretion_rate, - dtnova*1e-6); - */ - - star->time_prev_nova = stardata->model.time; - } - - /* limit timestep to dtnova * 0.1 */ - Limit_timestep(*dt,0.1*dtnova*1e-6,star,DT_LIMIT_NOVAE); - } + /* + * Hence the timestep limit in Myr + */ + const Time dtlim = + stardata->preferences->timestep_multipliers[DT_LIMIT_NOVAE] * + dtnova; + /* + * limit timestep because of novae + */ + Limit_timestep(*dt, + dtlim, + star, + DT_LIMIT_NOVAE); - /* update next nova time */ - star->time_next_nova = star->time_prev_nova + star->dtnova*1e-6; - } } if(star->starnum == 0) diff --git a/tbse b/tbse index 2ef5d1c97aaca5edf29ec5efb715c29abe78b4e6..b9d1a5d9e950e04a6c3baa07c8b266259564c128 100755 --- a/tbse +++ b/tbse @@ -827,7 +827,7 @@ NOVA_RETENTION_METHOD=NOVA_RETENTION_ALGORITHM_CONSTANT NOVA_RETENTION_FRACTION=1e-3 # Explode individual novae? -INDIVIDUAL_NOVAE=True +INDIVIDUAL_NOVAE=False # Reverse accretion beta (Shara+ 1986) : # accrete beta * the ejected mass back onto the companion.