diff --git a/src/cooling/const_lambda/cooling.h b/src/cooling/const_lambda/cooling.h index 6f1748fd46c43162c5dea258aeb5efd397f91370..57b58fed798dd68b5d7438f836bc005191c785e7 100644 --- a/src/cooling/const_lambda/cooling.h +++ b/src/cooling/const_lambda/cooling.h @@ -42,29 +42,29 @@ /** * @brief Calculates du/dt in CGS units for a particle. * - * @param phys_const The physical constants in internal units. - * @param us The internal system of units. + * The cooling rate is \f$\frac{du}{dt} = -\Lambda \frac{n_H^2}{\rho} \f$. + * * @param cosmo The current cosmological model. * @param hydro_props The properties of the hydro scheme. * @param cooling The #cooling_function_data used in the run. * @param p Pointer to the particle data.. */ __attribute__((always_inline)) INLINE static double cooling_rate_cgs( - const struct cosmology* restrict cosmo, - const struct hydro_props* hydro_props, + const struct cosmology* cosmo, const struct hydro_props* hydro_props, const struct cooling_function_data* cooling, const struct part* p) { /* Get particle density */ const double rho = hydro_get_physical_density(p, cosmo); - const double rho_cgs = rho * cooling->conv_factor_cgs_density; + const double rho_cgs = rho * cooling->conv_factor_density_to_cgs; - /* Get cooling function properties */ + /* Get Hydrogen mass fraction */ const double X_H = hydro_props->hydrogen_mass_fraction; - /* Calculate du_dt */ - const double du_dt_cgs = -cooling->lambda_cgs * - (X_H * rho_cgs / cooling->proton_mass_cgs) * - (X_H * rho_cgs / cooling->proton_mass_cgs) / rho_cgs; + /* Hydrogen number density (X_H * rho / m_p) */ + const double n_H_cgs = X_H * rho_cgs * cooling->proton_mass_cgs_inv; + + /* Calculate du_dt (Lambda * n_H^2 / rho) */ + const double du_dt_cgs = -cooling->lambda_cgs * n_H_cgs * n_H_cgs / rho_cgs; return du_dt_cgs; } @@ -75,9 +75,12 @@ __attribute__((always_inline)) INLINE static double cooling_rate_cgs( * @param phys_const The physical constants in internal units. * @param us The internal system of units. * @param cosmo The current cosmological model. + * @param hydro_props The properties of the hydro scheme. * @param cooling The #cooling_function_data used in the run. * @param p Pointer to the particle data. + * @param xp Pointer to the particle' extended data. * @param dt The time-step of this particle. + * @param dt_therm The time-step operator used for thermal quantities. */ __attribute__((always_inline)) INLINE static void cooling_cool_part( const struct phys_const* restrict phys_const, @@ -88,48 +91,64 @@ __attribute__((always_inline)) INLINE static void cooling_cool_part( struct part* restrict p, struct xpart* restrict xp, const float dt, const float dt_therm) { + /* Nothing to do here? */ if (dt == 0.) return; /* Internal energy floor */ - const double u_floor = hydro_props->minimal_internal_energy; + const float u_floor = hydro_props->minimal_internal_energy; /* Current energy */ - const double u_old = hydro_get_physical_internal_energy2(p, xp, cosmo); + const float u_old = hydro_get_physical_internal_energy2(p, xp, cosmo); /* Current du_dt in physical coordinates */ - const double hydro_du_dt = hydro_get_physical_internal_energy_dt(p, cosmo); + const float hydro_du_dt = hydro_get_physical_internal_energy_dt(p, cosmo); - /* Calculate cooling du_dt */ + /* Calculate cooling du_dt (in cgs units) */ const double cooling_du_dt_cgs = cooling_rate_cgs(cosmo, hydro_props, cooling, p); /* Convert to internal units */ - double cooling_du_dt = - cooling_du_dt_cgs / cooling->conv_factor_cgs_energy_rate; - - /* Integrate cooling equation to enforce energy floor */ - /* Factor of 1.5 included since timestep could potentially double */ - if (u_old + (hydro_du_dt * dt_therm + cooling_du_dt * dt) * 2.5f < u_floor) { - cooling_du_dt = - 0.; //-(u_old + 2.5f * dt * hydro_du_dt - u_floor) / (2.5f * dt); - } + float cooling_du_dt = + cooling_du_dt_cgs * cooling->conv_factor_energy_rate_from_cgs; /* Add cosmological term */ cooling_du_dt *= cosmo->a * cosmo->a; + float total_du_dt = hydro_du_dt + cooling_du_dt; + + /* We now need to check that we are not going to go below any of the limits */ + + /* First, check whether we may end up below the minimal energy after + * this step 1/2 kick + another 1/2 kick that could potentially be for + * a time-step twice as big. We hence check for 1.5 delta_t. */ + if (u_old + total_du_dt * 1.5 * dt_therm < u_floor) { + total_du_dt = (u_floor - u_old) / (1.5f * dt_therm); + } + + /* Second, check whether the energy used in the prediction could get negative. + * We need to check for the 1/2 dt kick followed by a full time-step drift + * that could potentially be for a time-step twice as big. We hence check + * for 2.5 delta_t but this time against 0 energy not the minimum */ + if (u_old + total_du_dt * 2.5 * dt_therm < 0.) { + total_du_dt = -u_old / ((2.5f + 0.0001f) * dt_therm); + } + /* Update the internal energy time derivative */ - hydro_set_physical_internal_energy_dt(p, cosmo, hydro_du_dt + cooling_du_dt); + hydro_set_physical_internal_energy_dt(p, cosmo, total_du_dt); - /* Store the radiated energy */ - xp->cooling_data.radiated_energy += -hydro_get_mass(p) * cooling_du_dt * dt; + /* Store the radiated energy (assuming we did not hit the limiter) */ + xp->cooling_data.radiated_energy += + -hydro_get_mass(p) * cooling_du_dt * dt_therm; } /** - * @brief Computes the time-step due to cooling + * @brief Computes the time-step due to cooling for this particle. * * @param cooling The #cooling_function_data used in the run. * @param phys_const The physical constants in internal units. + * @param us The internal system of units. * @param cosmo The current cosmological model. + * @param hydro_props The properties of the hydro scheme. * @param us The internal system of units. * @param p Pointer to the particle data. */ @@ -140,30 +159,34 @@ __attribute__((always_inline)) INLINE static float cooling_timestep( const struct unit_system* restrict us, const struct hydro_props* hydro_props, const struct part* restrict p) { - /* /\* Get current internal energy *\/ */ - /* const float u = hydro_get_physical_internal_energy(p, cosmo); */ - /* float cooling_du_dt = */ - /* cooling_rate(phys_const, us, cosmo, hydro_props, cooling, p); */ - - /* /\* Add cosmological term *\/ */ - /* cooling_du_dt *= cosmo->a * cosmo->a; */ - - /* /\* If we are close to (or below) the energy floor, we ignore the condition - * *\/ */ - /* if (u < 1.01f * hydro_props->minimal_internal_energy) */ - /* return FLT_MAX; */ - /* else */ - /* return cooling->cooling_tstep_mult * u / fabsf(cooling_du_dt); */ - return FLT_MAX; + /* Get current internal energy and cooling rate */ + const float u = hydro_get_physical_internal_energy(p, cosmo); + const double cooling_du_dt_cgs = + cooling_rate_cgs(cosmo, hydro_props, cooling, p); + + /* Convert to internal units */ + const float cooling_du_dt = + cooling_du_dt_cgs * cooling->conv_factor_energy_rate_from_cgs; + + /* If we are close to (or below) the limit, we ignore the condition */ + if (u < 1.01f * hydro_props->minimal_internal_energy) + return FLT_MAX; + else + return cooling->cooling_tstep_mult * u / fabsf(cooling_du_dt); } /** * @brief Sets the cooling properties of the (x-)particles to a valid start * state. * + * Nothing to do here. Just set the radiated energy counter to 0. + * + * @param phys_const The physical constants in internal units. + * @param cooling The properties of the cooling function. + * @param us The internal system of units. + * @param cosmo The current cosmological model. * @param p Pointer to the particle data. * @param xp Pointer to the extended particle data. - * @param cooling The properties of the cooling function. */ __attribute__((always_inline)) INLINE static void cooling_first_init_part( const struct phys_const* restrict phys_const, @@ -206,17 +229,16 @@ static INLINE void cooling_init_backend(struct swift_params* parameter_file, parameter_file, "LambdaCooling:cooling_tstep_mult"); /* Some useful conversion values */ - cooling->conv_factor_cgs_density = + cooling->conv_factor_density_to_cgs = units_cgs_conversion_factor(us, UNIT_CONV_DENSITY); - cooling->conv_factor_cgs_energy = + cooling->conv_factor_energy_rate_from_cgs = + units_cgs_conversion_factor(us, UNIT_CONV_TIME) / units_cgs_conversion_factor(us, UNIT_CONV_ENERGY_PER_UNIT_MASS); - cooling->conv_factor_cgs_energy_rate = - units_cgs_conversion_factor(us, UNIT_CONV_ENERGY_PER_UNIT_MASS) / - units_cgs_conversion_factor(us, UNIT_CONV_TIME); /* Useful constants */ - cooling->proton_mass_cgs = phys_const->const_proton_mass * - units_cgs_conversion_factor(us, UNIT_CONV_MASS); + cooling->proton_mass_cgs_inv = + 1. / (phys_const->const_proton_mass * + units_cgs_conversion_factor(us, UNIT_CONV_MASS)); } /** @@ -229,8 +251,6 @@ static INLINE void cooling_print_backend( message("Cooling function is 'Constant lambda' with Lambda=%g [cgs]", cooling->lambda_cgs); - - message("%e", cooling->proton_mass_cgs); } #endif /* SWIFT_COOLING_CONST_LAMBDA_H */ diff --git a/src/cooling/const_lambda/cooling_io.h b/src/cooling/const_lambda/cooling_io.h index 89c9471a291a4a6a5740a8c6c816913cbc6316a0..5f517be2a66019d94d9a32e7399f6e465c608782 100644 --- a/src/cooling/const_lambda/cooling_io.h +++ b/src/cooling/const_lambda/cooling_io.h @@ -44,7 +44,9 @@ __attribute__((always_inline)) INLINE static void cooling_write_flavour( /** * @brief Specifies which particle fields to write to a dataset * - * @param parts The particle array. + * Nothing to write for this scheme. + * + * @param xparts The extended particle array. * @param list The list of i/o properties to write. * @param cooling The #cooling_function_data * @@ -53,6 +55,7 @@ __attribute__((always_inline)) INLINE static void cooling_write_flavour( __attribute__((always_inline)) INLINE static int cooling_write_particles( const struct xpart* xparts, struct io_props* list, const struct cooling_function_data* cooling) { + return 0; } diff --git a/src/cooling/const_lambda/cooling_struct.h b/src/cooling/const_lambda/cooling_struct.h index 68d0cb0b695719a2c06d24893ac18ce0884437e2..0f4fc7d0806fc83ca7e74b70c7dc1cddfaa8a072 100644 --- a/src/cooling/const_lambda/cooling_struct.h +++ b/src/cooling/const_lambda/cooling_struct.h @@ -32,17 +32,14 @@ struct cooling_function_data { double lambda_cgs; /*! Conversion factor from internal units to cgs for density */ - double conv_factor_cgs_density; + double conv_factor_density_to_cgs; - /*! Conversion factor from internal units to cgs for internal energy */ - double conv_factor_cgs_energy; - - /*! Conversion factor from internal units to cgs for internal energy + /*! Conversion factor from internal units from cgs for internal energy * derivative */ - double conv_factor_cgs_energy_rate; + double conv_factor_energy_rate_from_cgs; - /*! Proton mass in cgs units */ - double proton_mass_cgs; + /*! Inverse of the proton mass in cgs units [g^-1] */ + double proton_mass_cgs_inv; /*! Constant multiplication factor for time-step criterion */ float cooling_tstep_mult;