Commit 4d592c18 authored by Matthieu Schaller's avatar Matthieu Schaller
Browse files

Merge branch 'fix_cooling_bug' into 'master'

Fix cooling bug

Gas particles no longer cool below the energy floor if the timestep increases.

Changed CoolingHaloWithSpin example so that gas particle masses are more sensible.

See merge request !307
parents f272054a 2c32b1e7
......@@ -9,8 +9,8 @@ InternalUnitSystem:
# Parameters governing the time integration
TimeIntegration:
time_begin: 0. # The starting time of the simulation (in internal units).
time_end: 10. # The end time of the simulation (in internal units).
dt_min: 1e-10 # The minimal time-step size of the simulation (in internal units).
time_end: 10. # The end time of the simulation (in internal units).
dt_min: 1e-5 # The minimal time-step size of the simulation (in internal units).
dt_max: 1e-1 # The maximal time-step size of the simulation (in internal units).
# Parameters governing the conserved quantities statistics
......@@ -48,4 +48,4 @@ LambdaCooling:
minimum_temperature: 1.0e4 # Minimal temperature (Kelvin)
mean_molecular_weight: 0.59 # Mean molecular weight
hydrogen_mass_abundance: 0.75 # Hydrogen mass abundance (dimensionless)
cooling_tstep_mult: 1.0 # Dimensionless pre-factor for the time-step condition
cooling_tstep_mult: 0.1 # Dimensionless pre-factor for the time-step condition
......@@ -28,7 +28,7 @@ unit_mass_cgs = float(params.attrs["InternalUnitSystem:UnitMass_in_cgs"])
unit_length_cgs = float(params.attrs["InternalUnitSystem:UnitLength_in_cgs"])
unit_velocity_cgs = float(params.attrs["InternalUnitSystem:UnitVelocity_in_cgs"])
unit_time_cgs = unit_length_cgs / unit_velocity_cgs
v_c = float(params.attrs["SoftenedIsothermalPotential:vrot"])
v_c = float(params.attrs["IsothermalPotential:vrot"])
v_c_cgs = v_c * unit_velocity_cgs
lambda_cgs = float(params.attrs["LambdaCooling:lambda_cgs"])
X_H = float(params.attrs["LambdaCooling:hydrogen_mass_abundance"])
......@@ -101,18 +101,18 @@ for i in range(n_snaps):
rho_0 = density[0]
rho_analytic_init = rho_0 * (radial_bin_mids/r_0)**(-2)
plt.plot(radial_bin_mids,density/rho_analytic_init,'ko',label = "Average density of shell")
#plt.plot(t,rho_analytic,label = "Initial analytic density profile"
plt.plot(radial_bin_mids,density,'ko',label = "Average density of shell")
plt.plot(radial_bin_mids,rho_analytic_init,label = "Initial analytic density profile")
plt.xlabel(r"$r / r_{vir}$")
plt.ylabel(r"$\rho / \rho_{init})$")
plt.ylabel(r"$(\rho / \rho_{init})$")
plt.title(r"$\mathrm{Time}= %.3g \, s \, , \, %d \, \, \mathrm{particles} \,,\, v_c = %.1f \, \mathrm{km / s}$" %(snap_time_cgs,N,v_c))
#plt.ylim((1.e-2,1.e1))
plt.plot((r_cool_over_r_vir,r_cool_over_r_vir),(0,20),'r',label = "Cooling radius")
plt.plot((r_cool_over_r_vir,r_cool_over_r_vir),(1.0e-4,1.0e4),'r',label = "Cooling radius")
plt.xlim((radial_bin_mids[0],max_r))
plt.ylim((0,20))
plt.plot((0,max_r),(1,1))
plt.ylim((1.0e-4,1.0e4))
#plt.plot((0,max_r),(1,1))
#plt.xscale('log')
#plt.yscale('log')
plt.yscale('log')
plt.legend(loc = "upper right")
plot_filename = "density_profile_%03d.png" %i
plt.savefig(plot_filename,format = "png")
......
......@@ -46,7 +46,7 @@ unit_mass_cgs = float(params.attrs["InternalUnitSystem:UnitMass_in_cgs"])
unit_length_cgs = float(params.attrs["InternalUnitSystem:UnitLength_in_cgs"])
unit_velocity_cgs = float(params.attrs["InternalUnitSystem:UnitVelocity_in_cgs"])
unit_time_cgs = unit_length_cgs / unit_velocity_cgs
v_c = float(params.attrs["SoftenedIsothermalPotential:vrot"])
v_c = float(params.attrs["IsothermalPotential:vrot"])
v_c_cgs = v_c * unit_velocity_cgs
lambda_cgs = float(params.attrs["LambdaCooling:lambda_cgs"])
X_H = float(params.attrs["LambdaCooling:hydrogen_mass_abundance"])
......
......@@ -36,6 +36,7 @@ h = 0.67777 # hubble parameter
gamma = 5./3.
eta = 1.2349
spin_lambda = 0.05 #spin parameter
f_b = 0.2 #baryon fraction
# First set unit velocity and then the circular velocity parameter for the isothermal potential
const_unit_velocity_in_cgs = 1.e5 #kms^-1
......@@ -99,6 +100,8 @@ grp.attrs["PeriodicBoundariesOn"] = periodic
# set seed for random number
np.random.seed(1234)
gas_mass = f_b * np.sqrt(3.) / 2. #virial mass of halo is 1, virial radius is 1, enclosed mass scales with r
gas_particle_mass = gas_mass / float(N)
# Positions
# r^(-2) distribution corresponds to uniform distribution in radius
......@@ -164,12 +167,12 @@ N = x_coords.size
print "Number of particles in the box = " , N
#make the coords and radius arrays again
coords_2 = np.zeros((N,3))
coords_2[:,0] = x_coords
coords_2[:,1] = y_coords
coords_2[:,2] = z_coords
coords= np.zeros((N,3))
coords[:,0] = x_coords
coords[:,1] = y_coords
coords[:,2] = z_coords
radius = np.sqrt((coords_2[:,0]-boxSize/2.)**2 + (coords_2[:,1]-boxSize/2.)**2 + (coords_2[:,2]-boxSize/2.)**2)
radius = np.sqrt((coords[:,0]-boxSize/2.)**2 + (coords[:,1]-boxSize/2.)**2 + (coords[:,2]-boxSize/2.)**2)
#now give particle's velocities
v = np.zeros((N,3))
......@@ -184,7 +187,7 @@ print "J =", J
omega = np.zeros((N,3))
for i in range(N):
omega[i,2] = 3.*J / radius[i]
v[i,:] = np.cross(omega[i,:],(coords_2[i,:]-boxSize/2.))
v[i,:] = np.cross(omega[i,:],(coords[i,:]-boxSize/2.))
# Header
grp = file.create_group("/Header")
......@@ -202,16 +205,15 @@ grp.attrs["Dimension"] = 3
grp = file.create_group("/PartType0")
ds = grp.create_dataset('Coordinates', (N, 3), 'd')
ds[()] = coords_2
coords_2 = np.zeros(1)
ds[()] = coords
coords = np.zeros(1)
ds = grp.create_dataset('Velocities', (N, 3), 'f')
ds[()] = v
v = np.zeros(1)
# All particles of equal mass
mass = 1. / N
m = np.full((N,),mass)
m = np.full((N,),gas_particle_mass)
ds = grp.create_dataset('Masses', (N, ), 'f')
ds[()] = m
m = np.zeros(1)
......
......@@ -46,7 +46,7 @@ unit_mass_cgs = float(params.attrs["InternalUnitSystem:UnitMass_in_cgs"])
unit_length_cgs = float(params.attrs["InternalUnitSystem:UnitLength_in_cgs"])
unit_velocity_cgs = float(params.attrs["InternalUnitSystem:UnitVelocity_in_cgs"])
unit_time_cgs = unit_length_cgs / unit_velocity_cgs
v_c = float(params.attrs["SoftenedIsothermalPotential:vrot"])
v_c = float(params.attrs["IsothermalPotential:vrot"])
v_c_cgs = v_c * unit_velocity_cgs
header = f["Header"]
N = header.attrs["NumPart_Total"][0]
......
......@@ -89,10 +89,9 @@ __attribute__((always_inline)) INLINE static void cooling_cool_part(
float cooling_du_dt = cooling_rate(phys_const, us, cooling, p);
/* Integrate cooling equation to enforce energy floor */
if (u_old + hydro_du_dt * dt < u_floor) {
cooling_du_dt = 0.f;
} else if (u_old + (hydro_du_dt + cooling_du_dt) * dt < u_floor) {
cooling_du_dt = (u_old + dt * hydro_du_dt - u_floor) / dt;
/* Factor of 1.5 included since timestep could potentially double */
if (u_old + (hydro_du_dt + cooling_du_dt) * 1.5f * dt < u_floor) {
cooling_du_dt = -(u_old + 1.5f * dt * hydro_du_dt - u_floor) / (1.5f * dt);
}
/* Update the internal energy time derivative */
......
......@@ -377,9 +377,13 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra(
struct part *restrict p, struct xpart *restrict xp, float dt) {
/* Do not decrease the entropy by more than a factor of 2 */
const float entropy_change = p->entropy_dt * dt;
xp->entropy_full =
max(xp->entropy_full + entropy_change, 0.5f * xp->entropy_full);
if (p->entropy_dt < -0.5f * xp->entropy_full / dt) {
/* message("Warning! Limiting entropy_dt. Possible cooling error.\n
* entropy_full = %g \n entropy_dt * dt =%g \n", */
/* xp->entropy_full,p->entropy_dt * dt); */
p->entropy_dt = -0.5f * xp->entropy_full / dt;
}
xp->entropy_full += p->entropy_dt * dt;
/* Compute the pressure */
const float pressure = gas_pressure_from_entropy(p->rho, xp->entropy_full);
......
......@@ -360,8 +360,10 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra(
struct part *restrict p, struct xpart *restrict xp, float dt) {
/* Do not decrease the energy by more than a factor of 2*/
const float u_change = p->u_dt * dt;
xp->u_full = max(xp->u_full + u_change, 0.5f * xp->u_full);
if (p->u_dt < -0.5f * xp->u_full / dt) {
p->u_dt = -0.5f * xp->u_full / dt;
}
xp->u_full += p->u_dt * dt;
/* Compute the pressure */
const float pressure = gas_pressure_from_internal_energy(p->rho, xp->u_full);
......
......@@ -394,11 +394,10 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra(
struct part *restrict p, struct xpart *restrict xp, float dt) {
/* Do not decrease the entropy (temperature) by more than a factor of 2*/
const float entropy_change = p->entropy_dt * dt;
if (entropy_change > -0.5f * xp->entropy_full)
xp->entropy_full += entropy_change;
else
xp->entropy_full *= 0.5f;
if (p->entropy_dt < -0.5f * xp->entropy_full / dt) {
p->entropy_dt = -0.5f * xp->entropy_full / dt;
}
xp->entropy_full += p->entropy_dt * dt;
/* Compute the pressure */
const float pressure =
......
......@@ -68,8 +68,8 @@
*separation.
* @param partId The running counter of IDs.
*/
struct part *make_particles(size_t count, double *offset, double spacing, double h,
long long *partId) {
struct part *make_particles(size_t count, double *offset, double spacing,
double h, long long *partId) {
struct part *particles;
if (posix_memalign((void **)&particles, part_align,
......@@ -281,7 +281,7 @@ void test_interactions(struct part test_part, struct part *parts, size_t count,
}
const ticks tic = getticks();
/* Perform serial interaction */
/* Perform serial interaction */
#ifdef __ICC
#pragma novector
#endif
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment