diff --git a/src/hydro/AnarchyDU/hydro_iact.h b/src/hydro/AnarchyDU/hydro_iact.h index d1d3b1f6c0e4941539044d14bda1dd9f7a5ca615..27353e78bac4f848a5d7d1c53ff62648613f1b2d 100644 --- a/src/hydro/AnarchyDU/hydro_iact.h +++ b/src/hydro/AnarchyDU/hydro_iact.h @@ -1,5 +1,5 @@ /******************************************************************************* - * This file is part* of SWIFT. + * This file is part of SWIFT. * Coypright (c) 2019 Josh Borrow (joshua.borrow@durham.ac.uk) & * Matthieu Schaller (matthieu.schaller@durham.ac.uk) * @@ -33,10 +33,10 @@ #include "./hydro_parameters.h" /** - * @brief Density interaction between two part*icles. + * @brief Density interaction between two particles. * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. @@ -109,10 +109,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_density( } /** - * @brief Density interaction between two part*icles (non-symmetric). + * @brief Density interaction between two particles (non-symmetric). * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. @@ -292,10 +292,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_gradient( } /** - * @brief Force interaction between two part*icles. + * @brief Force interaction between two particles. * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. @@ -418,10 +418,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_force( } /** - * @brief Force interaction between two part*icles (non-symmetric). + * @brief Force interaction between two particles (non-symmetric). * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. @@ -538,8 +538,8 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_force( /** * @brief Timestep limiter loop * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. @@ -558,8 +558,8 @@ __attribute__((always_inline)) INLINE static void runner_iact_limiter( /** * @brief Timestep limiter loop (non-symmetric version) * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. diff --git a/src/hydro/AnarchyDU/hydro_io.h b/src/hydro/AnarchyDU/hydro_io.h index fcec103b1e634a793268851935392e51a1611a97..db9995c3fe8a5089415dc9152a44a655ec97f0f3 100644 --- a/src/hydro/AnarchyDU/hydro_io.h +++ b/src/hydro/AnarchyDU/hydro_io.h @@ -10,7 +10,7 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR DURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License diff --git a/src/hydro/AnarchyPU/hydro_iact.h b/src/hydro/AnarchyPU/hydro_iact.h index bf683fb447a3c6aa10ca750e5c967356f9dabbfd..106fbdbcd42b4b7f2f837d542496551445c4b752 100644 --- a/src/hydro/AnarchyPU/hydro_iact.h +++ b/src/hydro/AnarchyPU/hydro_iact.h @@ -35,10 +35,10 @@ #include "./hydro_parameters.h" /** - * @brief Density interaction between two part*icles. + * @brief Density interaction between two particles. * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. @@ -117,10 +117,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_density( } /** - * @brief Density interaction between two part*icles (non-symmetric). + * @brief Density interaction between two particles (non-symmetric). * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. @@ -304,10 +304,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_gradient( } /** - * @brief Force interaction between two part*icles. + * @brief Force interaction between two particles. * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. @@ -434,10 +434,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_force( } /** - * @brief Force interaction between two part*icles (non-symmetric). + * @brief Force interaction between two particles (non-symmetric). * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. @@ -557,8 +557,8 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_force( /** * @brief Timestep limiter loop * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. @@ -577,8 +577,8 @@ __attribute__((always_inline)) INLINE static void runner_iact_limiter( /** * @brief Timestep limiter loop (non-symmetric version) * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. diff --git a/src/hydro/Default/hydro.h b/src/hydro/Default/hydro.h index 4bcc0bcd4fa4ebaf8f43d738230c597f19873ce5..694441c8b02f1071119d41df9b70999efd75be1f 100644 --- a/src/hydro/Default/hydro.h +++ b/src/hydro/Default/hydro.h @@ -1,6 +1,7 @@ /******************************************************************************* * This file is part of SWIFT. - * Coypright (c) 2015 Matthieu Schaller (matthieu.schaller@durham.ac.uk) + * Coypright (c) 2019 Josh Borrow (joshua.borrow@durham.ac.uk) & + * Matthieu Schaller (matthieu.schaller@durham.ac.uk) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published @@ -19,6 +20,14 @@ #ifndef SWIFT_DEFAULT_HYDRO_H #define SWIFT_DEFAULT_HYDRO_H +/** + * @file Default/hydro.h + * @brief Density-Energy conservative implementation of SPH, + * with added diffusive physics (Cullen & Denhen 2011 AV, + * Price 2017 (PHANTOM) diffusion) (Non-neighbour loop + * equations) + */ + #include "adiabatic_index.h" #include "approx_math.h" #include "cosmology.h" @@ -38,6 +47,10 @@ * @brief Returns the comoving internal energy of a particle at the last * time the particle was kicked. * + * For implementations where the main thermodynamic variable + * is not internal energy, this function computes the internal + * energy from the thermodynamic variable. + * * @param p The particle of interest * @param xp The extended data of the particle of interest. */ @@ -52,6 +65,11 @@ hydro_get_comoving_internal_energy(const struct part *restrict p, * @brief Returns the physical internal energy of a particle at the last * time the particle was kicked. * + * For implementations where the main thermodynamic variable + * is not internal energy, this function computes the internal + * energy from the thermodynamic variable and converts it to + * physical coordinates. + * * @param p The particle of interest. * @param xp The extended data of the particle of interest. * @param cosmo The cosmological model. @@ -93,6 +111,8 @@ hydro_get_drifted_physical_internal_energy(const struct part *restrict p, /** * @brief Returns the comoving pressure of a particle * + * Computes the pressure based on the particle's properties. + * * @param p The particle of interest */ __attribute__((always_inline)) INLINE static float hydro_get_comoving_pressure( @@ -104,21 +124,27 @@ __attribute__((always_inline)) INLINE static float hydro_get_comoving_pressure( /** * @brief Returns the physical pressure of a particle * + * Computes the pressure based on the particle's properties and + * convert it to physical coordinates. + * * @param p The particle of interest * @param cosmo The cosmological model. */ __attribute__((always_inline)) INLINE static float hydro_get_physical_pressure( const struct part *restrict p, const struct cosmology *cosmo) { - return cosmo->a_factor_pressure * - gas_pressure_from_internal_energy(p->rho, p->u); + return cosmo->a_factor_pressure * hydro_get_comoving_pressure(p); } /** * @brief Returns the comoving entropy of a particle at the last * time the particle was kicked. * - * @param p The particle of interest. + * For implementations where the main thermodynamic variable + * is not entropy, this function computes the entropy from + * the thermodynamic variable. + * + * @param p The particle of interest * @param xp The extended data of the particle of interest. */ __attribute__((always_inline)) INLINE static float hydro_get_comoving_entropy( @@ -131,6 +157,11 @@ __attribute__((always_inline)) INLINE static float hydro_get_comoving_entropy( * @brief Returns the physical entropy of a particle at the last * time the particle was kicked. * + * For implementations where the main thermodynamic variable + * is not entropy, this function computes the entropy from + * the thermodynamic variable and converts it to + * physical coordinates. + * * @param p The particle of interest. * @param xp The extended data of the particle of interest. * @param cosmo The cosmological model. @@ -180,7 +211,7 @@ hydro_get_drifted_physical_entropy(const struct part *restrict p, __attribute__((always_inline)) INLINE static float hydro_get_comoving_soundspeed(const struct part *restrict p) { - return p->force.soundspeed; + return gas_soundspeed_from_internal_energy(p->rho, p->u); } /** @@ -193,7 +224,7 @@ __attribute__((always_inline)) INLINE static float hydro_get_physical_soundspeed(const struct part *restrict p, const struct cosmology *cosmo) { - return cosmo->a_factor_sound_speed * p->force.soundspeed; + return cosmo->a_factor_sound_speed * hydro_get_comoving_soundspeed(p); } /** @@ -208,14 +239,15 @@ __attribute__((always_inline)) INLINE static float hydro_get_comoving_density( } /** - * @brief Returns the physical density of a particle + * @brief Returns the comoving density of a particle. * * @param p The particle of interest + * @param cosmo The cosmological model. */ __attribute__((always_inline)) INLINE static float hydro_get_physical_density( const struct part *restrict p, const struct cosmology *cosmo) { - return p->rho * cosmo->a3_inv; + return cosmo->a3_inv * p->rho; } /** @@ -272,7 +304,7 @@ __attribute__((always_inline)) INLINE static void hydro_get_drifted_velocities( __attribute__((always_inline)) INLINE static float hydro_get_comoving_internal_energy_dt(const struct part *restrict p) { - return p->force.u_dt; + return p->u_dt; } /** @@ -287,11 +319,11 @@ __attribute__((always_inline)) INLINE static float hydro_get_physical_internal_energy_dt(const struct part *restrict p, const struct cosmology *cosmo) { - return p->force.u_dt * cosmo->a_factor_internal_energy; + return p->u_dt * cosmo->a_factor_internal_energy; } /** - * @brief Returns the time derivative of internal energy of a particle + * @brief Sets the time derivative of internal energy of a particle * * We assume a constant density. * @@ -301,7 +333,7 @@ hydro_get_physical_internal_energy_dt(const struct part *restrict p, __attribute__((always_inline)) INLINE static void hydro_set_comoving_internal_energy_dt(struct part *restrict p, float du_dt) { - p->force.u_dt = du_dt; + p->u_dt = du_dt; } /** @@ -318,7 +350,7 @@ hydro_set_physical_internal_energy_dt(struct part *restrict p, const struct cosmology *cosmo, float du_dt) { - p->force.u_dt = du_dt * cosmo->a_factor_internal_energy; + p->u_dt = du_dt / cosmo->a_factor_internal_energy; } /** @@ -372,9 +404,11 @@ hydro_set_drifted_physical_internal_energy(struct part *p, /* Compute the sound speed */ const float soundspeed = hydro_get_comoving_soundspeed(p); + const float pressure = hydro_get_comoving_pressure(p); /* Update variables. */ p->force.soundspeed = soundspeed; + p->force.pressure = pressure; } /** @@ -385,7 +419,7 @@ hydro_set_drifted_physical_internal_energy(struct part *p, */ __attribute__((always_inline)) INLINE static void hydro_set_viscosity_alpha( struct part *restrict p, float alpha) { - p->alpha = alpha; + p->viscosity.alpha = alpha; } /** @@ -403,9 +437,12 @@ hydro_set_viscosity_alpha_max_feedback(struct part *restrict p) { /** * @brief Computes the hydro time-step of a given particle * + * This function returns the time-step of a particle given its hydro-dynamical + * state. A typical time-step calculation would be the use of the CFL condition. + * * @param p Pointer to the particle data * @param xp Pointer to the extended particle data - * @param hydro_properties The constants used in the scheme + * @param hydro_properties The SPH parameters * @param cosmo The cosmological model. */ __attribute__((always_inline)) INLINE static float hydro_compute_timestep( @@ -413,18 +450,13 @@ __attribute__((always_inline)) INLINE static float hydro_compute_timestep( const struct hydro_props *restrict hydro_properties, const struct cosmology *restrict cosmo) { - const float CFL = hydro_properties->CFL_condition; + const float CFL_condition = hydro_properties->CFL_condition; /* CFL condition */ - const float dt_cfl = 2.f * kernel_gamma * CFL * cosmo->a * p->h / - (cosmo->a_factor_sound_speed * p->force.v_sig); - - /* Limit change in u */ - const float dt_u_change = - (p->force.u_dt != 0.0f) ? fabsf(const_max_u_change * p->u / p->force.u_dt) - : FLT_MAX; + const float dt_cfl = 2.f * kernel_gamma * CFL_condition * cosmo->a * p->h / + (cosmo->a_factor_sound_speed * p->viscosity.v_sig); - return min(dt_cfl, dt_u_change); + return dt_cfl; } /** @@ -437,11 +469,22 @@ __attribute__((always_inline)) INLINE static float hydro_compute_timestep( __attribute__((always_inline)) INLINE static void hydro_timestep_extra( struct part *p, float dt) {} +/** + * @brief Operations performed when a particle gets removed from the + * simulation volume. + * + * @param p The particle. + * @param xp The extended particle data. + */ +__attribute__((always_inline)) INLINE static void hydro_remove_part( + const struct part *p, const struct xpart *xp) {} + /** * @brief Prepares a particle for the density calculation. * * Zeroes all the relevant arrays in preparation for the sums taking place in - * the variaous density tasks + * the various density loop over neighbours. Typically, all fields of the + * density sub-structure of a particle get zeroed in here. * * @param p The particle to act upon * @param hs #hydro_space containing hydro specific space information. @@ -452,11 +495,13 @@ __attribute__((always_inline)) INLINE static void hydro_init_part( p->density.wcount = 0.f; p->density.wcount_dh = 0.f; p->rho = 0.f; - p->rho_dh = 0.f; - p->density.div_v = 0.f; + p->density.rho_dh = 0.f; + p->density.rot_v[0] = 0.f; p->density.rot_v[1] = 0.f; p->density.rot_v[2] = 0.f; + + p->viscosity.div_v = 0.f; } /** @@ -464,9 +509,13 @@ __attribute__((always_inline)) INLINE static void hydro_init_part( * * Multiplies the density and number of neighbours by the appropiate constants * and add the self-contribution term. + * Additional quantities such as velocity gradients will also get the final + * terms added to them here. + * + * Also adds/multiplies the cosmological terms if need be. * * @param p The particle to act upon - * @param cosmo The current cosmological model. + * @param cosmo The cosmological model. */ __attribute__((always_inline)) INLINE static void hydro_end_density( struct part *restrict p, const struct cosmology *cosmo) { @@ -479,33 +528,115 @@ __attribute__((always_inline)) INLINE static void hydro_end_density( /* Final operation on the density (add self-contribution). */ p->rho += p->mass * kernel_root; - p->rho_dh -= hydro_dimension * p->mass * kernel_root; + p->density.rho_dh -= hydro_dimension * p->mass * kernel_root; p->density.wcount += kernel_root; + p->density.wcount_dh -= hydro_dimension * kernel_root; /* Finish the calculation by inserting the missing h-factors */ p->rho *= h_inv_dim; - p->rho_dh *= h_inv_dim_plus_one; - p->density.wcount *= kernel_norm; - p->density.wcount_dh *= h_inv * kernel_gamma * kernel_norm; + p->density.rho_dh *= h_inv_dim_plus_one; + p->density.wcount *= h_inv_dim; + p->density.wcount_dh *= h_inv_dim_plus_one; - const float irho = 1.f / p->rho; + const float rho_inv = 1.f / p->rho; const float a_inv2 = cosmo->a2_inv; /* Finish calculation of the velocity curl components */ - p->density.rot_v[0] *= h_inv_dim_plus_one * a_inv2 * irho; - p->density.rot_v[1] *= h_inv_dim_plus_one * a_inv2 * irho; - p->density.rot_v[2] *= h_inv_dim_plus_one * a_inv2 * irho; + p->density.rot_v[0] *= h_inv_dim_plus_one * a_inv2 * rho_inv; + p->density.rot_v[1] *= h_inv_dim_plus_one * a_inv2 * rho_inv; + p->density.rot_v[2] *= h_inv_dim_plus_one * a_inv2 * rho_inv; /* Finish calculation of the velocity divergence */ - p->density.div_v *= h_inv_dim_plus_one * a_inv2 * irho; + p->viscosity.div_v *= h_inv_dim_plus_one * rho_inv * a_inv2; + p->viscosity.div_v += cosmo->H * hydro_dimension; } +/** + * @brief Prepare a particle for the gradient calculation. + * + * This function is called after the density loop and before the gradient loop. + * + * We use it to set the physical timestep for the particle and to copy the + * actual velocities, which we need to boost our interfaces during the flux + * calculation. We also initialize the variables used for the time step + * calculation. + * + * @param p The particle to act upon. + * @param xp The extended particle data to act upon. + * @param cosmo The cosmological model. + */ +__attribute__((always_inline)) INLINE static void hydro_prepare_gradient( + struct part *restrict p, struct xpart *restrict xp, + const struct cosmology *cosmo) { + + const float fac_B = cosmo->a_factor_Balsara_eps; + + /* Compute the norm of the curl */ + const float curl_v = sqrtf(p->density.rot_v[0] * p->density.rot_v[0] + + p->density.rot_v[1] * p->density.rot_v[1] + + p->density.rot_v[2] * p->density.rot_v[2]); + + /* Compute the norm of div v */ + const float abs_div_v = fabsf(p->viscosity.div_v); + + /* Compute the sound speed -- see theory section for justification */ + const float soundspeed = hydro_get_comoving_soundspeed(p); + const float pressure = hydro_get_comoving_pressure(p); + + /* Compute the Balsara switch */ + const float balsara = + abs_div_v / (abs_div_v + curl_v + 0.0001f * soundspeed * fac_B / p->h); + + /* Compute the "grad h" term */ + const float rho_inv = 1.f / p->rho; + const float grad_h_term = + 1.f / (1.f + hydro_dimension_inv * p->h * p->density.rho_dh * rho_inv); + + /* Update variables. */ + p->force.f = grad_h_term; + p->force.pressure = pressure; + p->force.soundspeed = soundspeed; + p->force.balsara = balsara; +} + +/** + * @brief Resets the variables that are required for a gradient calculation. + * + * This function is called after hydro_prepare_gradient. + * + * @param p The particle to act upon. + * @param xp The extended particle data to act upon. + * @param cosmo The cosmological model. + */ +__attribute__((always_inline)) INLINE static void hydro_reset_gradient( + struct part *restrict p) { + + p->viscosity.v_sig = 2.f * p->force.soundspeed; +} + +/** + * @brief Finishes the gradient calculation. + * + * Just a wrapper around hydro_gradients_finalize, which can be an empty method, + * in which case no gradients are used. + * + * This method also initializes the force loop variables. + * + * @param p The particle to act upon. + */ +__attribute__((always_inline)) INLINE static void hydro_end_gradient( + struct part *p) {} + /** * @brief Sets all particle fields to sensible values when the #part has 0 ngbs. * + * In the desperate case where a particle has no neighbours (likely because + * of the h_max ceiling), set the particle fields to something sensible to avoid + * NaNs in the next calculations. + * * @param p The particle to act upon * @param xp The extended particle data to act upon - * @param cosmo The current cosmological model. + * @param cosmo The cosmological model. */ __attribute__((always_inline)) INLINE static void hydro_part_has_no_neighbours( struct part *restrict p, struct xpart *restrict xp, @@ -518,13 +649,17 @@ __attribute__((always_inline)) INLINE static void hydro_part_has_no_neighbours( /* Re-set problematic values */ p->rho = p->mass * kernel_root * h_inv_dim; + p->viscosity.v_sig = 0.f; p->density.wcount = kernel_root * h_inv_dim; - p->rho_dh = 0.f; + p->density.rho_dh = 0.f; p->density.wcount_dh = 0.f; - p->density.div_v = 0.f; + p->density.rot_v[0] = 0.f; p->density.rot_v[1] = 0.f; p->density.rot_v[2] = 0.f; + + /* Probably not shocking, so this is safe to do */ + p->viscosity.div_v = 0.f; } /** @@ -548,62 +683,67 @@ __attribute__((always_inline)) INLINE static void hydro_prepare_force( struct part *restrict p, struct xpart *restrict xp, const struct cosmology *cosmo, const struct hydro_props *hydro_props, const float dt_alpha) { - const float fac_mu = cosmo->a_factor_mu; - - /* Some smoothing length multiples. */ - const float h = p->h; - const float h_inv = 1.0f / h; - /* Pre-compute some stuff for the balsara switch. */ - const float normDiv_v = fabs(p->density.div_v); - const float normRot_v = sqrtf(p->density.rot_v[0] * p->density.rot_v[0] + - p->density.rot_v[1] * p->density.rot_v[1] + - p->density.rot_v[2] * p->density.rot_v[2]); + /* Here we need to update the artificial viscosity */ - /* Compute this particle's sound speed. */ - const float u = p->u; - const float fc = p->force.soundspeed = - sqrtf(hydro_gamma * hydro_gamma_minus_one * u); + /* We use in this function that h is the radius of support */ + const float kernel_support_physical = p->h * cosmo->a * kernel_gamma; + const float kernel_support_physical_inv = 1.f / kernel_support_physical; + const float v_sig_physical = p->viscosity.v_sig * cosmo->a_factor_sound_speed; + const float soundspeed_physical = hydro_get_physical_soundspeed(p, cosmo); - /* Compute the derivative term */ - p->rho_dh = 1.f / (1.f + hydro_dimension_inv * p->h * p->rho_dh / p->rho); + const float sound_crossing_time_inverse = + soundspeed_physical * kernel_support_physical_inv; - /* Compute the P/Omega/rho2. */ - xp->omega = 1.0f + hydro_dimension_inv * h * p->rho_dh / p->rho; - p->force.P_over_rho2 = u * hydro_gamma_minus_one / (p->rho * xp->omega); + /* Construct time differential of div.v implicitly following the ANARCHY spec + */ - /* Balsara switch */ - p->force.balsara = - normDiv_v / (normDiv_v + normRot_v + 0.0001f * fac_mu * fc * h_inv); + const float div_v_dt = + dt_alpha == 0.f + ? 0.f + : (p->viscosity.div_v - p->viscosity.div_v_previous_step) / dt_alpha; - /* Set the AV property */ - p->alpha = hydro_props->viscosity.alpha; + /* Construct the source term for the AV; if shock detected this is _positive_ + * as div_v_dt should be _negative_ before the shock hits */ + const float S = kernel_support_physical * kernel_support_physical * + max(0.f, -1.f * div_v_dt); + /* 0.25 factor comes from our definition of v_sig (sum of soundspeeds rather + * than mean). */ + /* Note this is v_sig_physical squared, not comoving */ + const float v_sig_square = 0.25 * v_sig_physical * v_sig_physical; - /* Set the diffusion parameter */ - p->alpha_diff = hydro_props->diffusion.alpha; + /* Calculate the current appropriate value of the AV based on the above */ + const float alpha_loc = + hydro_props->viscosity.alpha_max * S / (v_sig_square + S); - /* Viscosity parameter decay time */ - /* const float tau = h / (2.f * const_viscosity_length * p->force.soundspeed); - */ + if (alpha_loc > p->viscosity.alpha) { + /* Reset the value of alpha to the appropriate value */ + p->viscosity.alpha = alpha_loc; + } else { + /* Integrate the alpha forward in time to decay back to alpha = alpha_loc */ + p->viscosity.alpha = + alpha_loc + (p->viscosity.alpha - alpha_loc) * + expf(-dt_alpha * sound_crossing_time_inverse * + hydro_props->viscosity.length); + } - /* Viscosity source term */ - /* const float S = max(-normDiv_v, 0.f); */ + /* Check that we did not hit the minimum */ + p->viscosity.alpha = + max(p->viscosity.alpha, hydro_props->viscosity.alpha_min); - /* Compute the particle's viscosity parameter time derivative */ - /* const float alpha_dot = (hydro_props->viscosity.alpha_max) - p->alpha) / - * tau + */ - /* (hydro_props->viscosity.alpha_max - p->alpha) * S; - */ + /* Set our old div_v to the one for the next loop */ + p->viscosity.div_v_previous_step = p->viscosity.div_v; - /* Update particle's viscosity paramter */ - /* p->alpha += alpha_dot * (p->ti_end - p->ti_begin) * timeBase; */ // MATTHIEU + /* Multiply the alpha value in here, as we want to limit on an individual + * basis! */ + p->force.balsara *= p->viscosity.alpha; } /** * @brief Reset acceleration fields of a particle * * Resets all hydro acceleration and time derivative fields in preparation - * for the sums taking place in the variaous force tasks + * for the sums taking place in the various force tasks. * * @param p The particle to act upon */ @@ -616,9 +756,8 @@ __attribute__((always_inline)) INLINE static void hydro_reset_acceleration( p->a_hydro[2] = 0.0f; /* Reset the time derivatives. */ - p->force.u_dt = 0.0f; + p->u_dt = 0.0f; p->force.h_dt = 0.0f; - p->force.v_sig = p->force.soundspeed; } /** @@ -636,14 +775,28 @@ __attribute__((always_inline)) INLINE static void hydro_reset_predicted_values( p->v[1] = xp->v_full[1]; p->v[2] = xp->v_full[2]; + /* Re-set the entropy */ p->u = xp->u_full; + + /* Compute the sound speed */ + const float pressure = gas_pressure_from_internal_energy(p->rho, p->u); + const float soundspeed = hydro_get_comoving_soundspeed(p); + + p->force.pressure = pressure; + p->force.soundspeed = soundspeed; } /** * @brief Predict additional particle fields forward in time when drifting * - * @param p The particle - * @param xp The extended data of the particle + * Additional hydrodynamic quantites are drifted forward in time here. These + * include thermal quantities (thermal energy or total energy or entropy, ...). + * + * Note the different time-step sizes used for the different quantities as they + * include cosmological factors. + * + * @param p The particle. + * @param xp The extended data of the particle. * @param dt_drift The drift time-step for positions. * @param dt_therm The drift time-step for thermal quantities. * @param cosmo The cosmological model. @@ -651,13 +804,13 @@ __attribute__((always_inline)) INLINE static void hydro_reset_predicted_values( * @param floor_props The properties of the entropy floor. */ __attribute__((always_inline)) INLINE static void hydro_predict_extra( - struct part *restrict p, struct xpart *restrict xp, float dt_drift, + struct part *restrict p, const struct xpart *restrict xp, float dt_drift, float dt_therm, const struct cosmology *cosmo, const struct hydro_props *hydro_props, const struct entropy_floor_properties *floor_props) { /* Predict the internal energy */ - p->u += p->force.u_dt * dt_therm; + p->u += p->u_dt * dt_therm; /* Check against entropy floor */ const float floor_A = entropy_floor(p, cosmo, floor_props); @@ -679,61 +832,143 @@ __attribute__((always_inline)) INLINE static void hydro_predict_extra( else p->h *= expf(w1); - /* Predict density */ + /* Predict density and weighted pressure */ const float w2 = -hydro_dimension * w1; - if (fabsf(w2) < 0.2f) - p->rho *= approx_expf(w2); /* 4th order expansion of exp(w) */ - else - p->rho *= expf(w2); + if (fabsf(w2) < 0.2f) { + const float expf_approx = + approx_expf(w2); /* 4th order expansion of exp(w) */ + p->rho *= expf_approx; + } else { + const float expf_exact = expf(w2); + p->rho *= expf_exact; + } + + /* Compute the new sound speed */ + const float pressure = gas_pressure_from_internal_energy(p->rho, p->u); + const float soundspeed = hydro_get_comoving_soundspeed(p); - /* Predict gradient term */ - p->force.P_over_rho2 = p->u * hydro_gamma_minus_one / (p->rho * xp->omega); + p->force.pressure = pressure; + p->force.soundspeed = soundspeed; } /** * @brief Finishes the force calculation. * - * Multiplies the forces and accelerationsby the appropiate constants + * Multiplies the force and accelerations by the appropiate constants + * and add the self-contribution term. In most cases, there is little + * to do here. + * + * Cosmological terms are also added/multiplied here. * * @param p The particle to act upon * @param cosmo The current cosmological model. */ __attribute__((always_inline)) INLINE static void hydro_end_force( struct part *restrict p, const struct cosmology *cosmo) { + p->force.h_dt *= p->h * hydro_dimension_inv; } /** * @brief Kick the additional variables * - * @param p The particle to act upon - * @param xp The particle extended data to act upon - * @param dt_therm The time-step for this kick (for thermodynamic quantities) + * Additional hydrodynamic quantites are kicked forward in time here. These + * include thermal quantities (thermal energy or total energy or entropy, ...). + * + * @param p The particle to act upon. + * @param xp The particle extended data to act upon. + * @param dt_therm The time-step for this kick (for thermodynamic quantities). + * @param dt_grav The time-step for this kick (for gravity quantities). + * @param dt_hydro The time-step for this kick (for hydro quantities). + * @param dt_kick_corr The time-step for this kick (for gravity corrections). + * @param cosmo The cosmological model. + * @param hydro_props The constants used in the scheme + * @param floor_props The properties of the entropy floor. */ __attribute__((always_inline)) INLINE static void hydro_kick_extra( struct part *restrict p, struct xpart *restrict xp, float dt_therm, float dt_grav, float dt_hydro, float dt_kick_corr, const struct cosmology *cosmo, const struct hydro_props *hydro_props, - const struct entropy_floor_properties *floor_props) {} + const struct entropy_floor_properties *floor_props) { + + /* Integrate the internal energy forward in time */ + const float delta_u = p->u_dt * dt_therm; + + /* Do not decrease the energy by more than a factor of 2*/ + xp->u_full = max(xp->u_full + delta_u, 0.5f * xp->u_full); + + /* Check against entropy floor */ + const float floor_A = entropy_floor(p, cosmo, floor_props); + const float floor_u = gas_internal_energy_from_entropy(p->rho, floor_A); + + /* Check against absolute minimum */ + const float min_u = + hydro_props->minimal_internal_energy / cosmo->a_factor_internal_energy; + + /* Take highest of both limits */ + const float energy_min = max(min_u, floor_u); + + if (xp->u_full < energy_min) { + xp->u_full = energy_min; + p->u_dt = 0.f; + } +} /** - * @brief Converts hydro quantity of a particle at the start of a run + * @brief Converts hydro quantity of a particle at the start of a run * - * Requires the density to be known + * This function is called once at the end of the engine_init_particle() + * routine (at the start of a calculation) after the densities of + * particles have been computed. + * This can be used to convert internal energy into entropy for instance. * * @param p The particle to act upon - * @param xp The extended data. + * @param xp The extended particle to act upon * @param cosmo The cosmological model. + * @param hydro_props The constants used in the scheme. */ __attribute__((always_inline)) INLINE static void hydro_convert_quantities( struct part *restrict p, struct xpart *restrict xp, - const struct cosmology *cosmo, const struct hydro_props *hydro_props) {} + const struct cosmology *cosmo, const struct hydro_props *hydro_props) { + + /* Convert the physcial internal energy to the comoving one. */ + /* u' = a^(3(g-1)) u */ + const float factor = 1.f / cosmo->a_factor_internal_energy; + p->u *= factor; + xp->u_full = p->u; + + /* Apply the minimal energy limit */ + const float min_comoving_energy = + hydro_props->minimal_internal_energy / cosmo->a_factor_internal_energy; + if (xp->u_full < min_comoving_energy) { + xp->u_full = min_comoving_energy; + p->u = min_comoving_energy; + p->u_dt = 0.f; + } + + /* Set the initial value of the artificial viscosity based on the non-variable + schemes for safety */ + + p->viscosity.alpha = hydro_props->viscosity.alpha; + /* Initialise this here to keep all the AV variables together */ + p->viscosity.div_v_previous_step = 0.f; + + /* Set the initial values for the thermal diffusion */ + p->diffusion.alpha = hydro_props->diffusion.alpha; + + const float pressure = gas_pressure_from_internal_energy(p->rho, p->u); + const float soundspeed = gas_soundspeed_from_internal_energy(p->rho, p->u); + + p->force.pressure = pressure; + p->force.soundspeed = soundspeed; +} /** * @brief Initialises the particles for the first time * * This function is called only once just after the ICs have been - * read in to do some conversions. + * read in to do some conversions or assignments between the particle + * and extended particle fields. * * @param p The particle to act upon * @param xp The extended particle data to act upon @@ -772,14 +1007,4 @@ hydro_set_init_internal_energy(struct part *p, float u_init) { p->u = u_init; } -/** - * @brief Operations performed when a particle gets removed from the - * simulation volume. - * - * @param p The particle. - * @param xp The extended particle data. - */ -__attribute__((always_inline)) INLINE static void hydro_remove_part( - const struct part *p, const struct xpart *xp) {} - #endif /* SWIFT_DEFAULT_HYDRO_H */ diff --git a/src/hydro/Default/hydro_debug.h b/src/hydro/Default/hydro_debug.h index 68367beaee97c285057cb055c1fbdbba5c370085..e9083870151feb984dc9c95d8f4cd33d1a80235f 100644 --- a/src/hydro/Default/hydro_debug.h +++ b/src/hydro/Default/hydro_debug.h @@ -1,6 +1,7 @@ /******************************************************************************* * This file is part of SWIFT. - * Coypright (c) 2016 Matthieu Schaller (matthieu.schaller@durham.ac.uk) + * Coypright (c) 2019 Josh Borrow (joshua.borrow@durham.ac.uk) & + * Matthieu Schaller (matthieu.schaller@durham.ac.uk) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published @@ -16,20 +17,31 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * ******************************************************************************/ + #ifndef SWIFT_DEFAULT_HYDRO_DEBUG_H #define SWIFT_DEFAULT_HYDRO_DEBUG_H +/** + * @file Default/hydro_debug.h + * @brief Density-Energy conservative implementation of SPH, + * with added diffusive physics (Cullen & Denhen 2011 AV, + * Price 2017 (PHANTOM) diffusion) (Debugging routines) + */ + __attribute__((always_inline)) INLINE static void hydro_debug_particle( const struct part* p, const struct xpart* xp) { printf( "x=[%.3e,%.3e,%.3e], " - "v=[%.3e,%.3e,%.3e],v_full=[%.3e,%.3e,%.3e] \n a=[%.3e,%.3e,%.3e],\n " - "h=%.3e, " - "wcount=%d, m=%.3e, dh_drho=%.3e, rho=%.3e, time_bin=%d wakeup=%d\n", + "v=[%.3e,%.3e,%.3e],v_full=[%.3e,%.3e,%.3e] \n a=[%.3e,%.3e,%.3e], " + "u=%.3e, du/dt=%.3e v_sig=%.3e, P=%.3e\n" + "h=%.3e, dh/dt=%.3e wcount=%d, m=%.3e, dh_drho=%.3e, rho=%.3e, \n" + "alpha=%.3e \n" + "time_bin=%d\n", p->x[0], p->x[1], p->x[2], p->v[0], p->v[1], p->v[2], xp->v_full[0], xp->v_full[1], xp->v_full[2], p->a_hydro[0], p->a_hydro[1], p->a_hydro[2], - p->h, (int)p->density.wcount, p->mass, p->rho_dh, p->rho, p->time_bin, - p->wakeup); + p->u, p->u_dt, p->viscosity.v_sig, hydro_get_comoving_pressure(p), p->h, + p->force.h_dt, (int)p->density.wcount, p->mass, p->density.rho_dh, p->rho, + p->viscosity.alpha, p->time_bin); } #endif /* SWIFT_DEFAULT_HYDRO_DEBUG_H */ diff --git a/src/hydro/Default/hydro_iact.h b/src/hydro/Default/hydro_iact.h index 8ce77b9e353bf38b31dbd7b7a5444c10f3f6b5bc..07c8f0edc3885376be828480492de10b35d857e3 100644 --- a/src/hydro/Default/hydro_iact.h +++ b/src/hydro/Default/hydro_iact.h @@ -1,6 +1,6 @@ /******************************************************************************* * This file is part of SWIFT. - * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk) + * Coypright (c) 2019 Josh Borrow (joshua.borrow@durham.ac.uk) & * Matthieu Schaller (matthieu.schaller@durham.ac.uk) * * This program is free software: you can redistribute it and/or modify @@ -20,25 +20,18 @@ #ifndef SWIFT_DEFAULT_HYDRO_IACT_H #define SWIFT_DEFAULT_HYDRO_IACT_H +/** + * @file Default/hydro_iact.h + * @brief Density-Energy conservative implementation of SPH, + * with added diffusive physics (Cullen & Denhen 2011 AV, + * Price 2017 (PHANTOM) diffusion) (interaction routines) + */ + #include "adiabatic_index.h" +#include "minmax.h" #include "./hydro_parameters.h" -/** - * @brief SPH interaction functions following the Gadget-2 version of SPH. - * - * The interactions computed here are the ones presented in the Gadget-2 paper - * and use the same - * numerical coefficients as the Gadget-2 code. When used with the Spline-3 - * kernel, the results - * should be equivalent to the ones obtained with Gadget-2 up to the rounding - * errors and interactions - * missed by the Gadget-2 tree-code neighbours search. - * - * The code uses internal energy instead of entropy as a thermodynamical - * variable. - */ - /** * @brief Density interaction between two particles. * @@ -46,66 +39,73 @@ * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of particle i. * @param hj Comoving smoothing-length of particle j. - * @param pi First particle. - * @param pj Second particle. + * @param pi First part*icle. + * @param pj Second part*icle. * @param a Current scale factor. * @param H Current Hubble parameter. */ __attribute__((always_inline)) INLINE static void runner_iact_density( - float r2, const float *dx, float hi, float hj, struct part *restrict pi, - struct part *restrict pj, float a, float H) { + float r2, const float* dx, float hi, float hj, struct part* pi, + struct part* pj, float a, float H) { - float r = sqrtf(r2), ri = 1.0f / r; - float xi, xj; - float h_inv; float wi, wj, wi_dx, wj_dx; - float mi, mj; - float dvdr; float dv[3], curlvr[3]; - int k; + + const float r = sqrtf(r2); /* Get the masses. */ - mi = pi->mass; - mj = pj->mass; + const float mi = pi->mass; + const float mj = pj->mass; + + /* Compute density of pi. */ + const float hi_inv = 1.f / hi; + const float ui = r * hi_inv; + + kernel_deval(ui, &wi, &wi_dx); + + pi->rho += mj * wi; + pi->density.rho_dh -= mj * (hydro_dimension * wi + ui * wi_dx); + + pi->density.wcount += wi; + pi->density.wcount_dh -= (hydro_dimension * wi + ui * wi_dx); + + /* Compute density of pj. */ + const float hj_inv = 1.f / hj; + const float uj = r * hj_inv; + kernel_deval(uj, &wj, &wj_dx); + + pj->rho += mi * wj; + pj->density.rho_dh -= mi * (hydro_dimension * wj + uj * wj_dx); + pj->density.wcount += wj; + pj->density.wcount_dh -= (hydro_dimension * wj + uj * wj_dx); + + /* Now we need to compute the div terms */ + const float r_inv = 1.f / r; + const float faci = mj * wi_dx * r_inv; + const float facj = mi * wj_dx * r_inv; /* Compute dv dot r */ dv[0] = pi->v[0] - pj->v[0]; dv[1] = pi->v[1] - pj->v[1]; dv[2] = pi->v[2] - pj->v[2]; - dvdr = dv[0] * dx[0] + dv[1] * dx[1] + dv[2] * dx[2]; - dvdr *= ri; + const float dvdr = dv[0] * dx[0] + dv[1] * dx[1] + dv[2] * dx[2]; + + pi->viscosity.div_v -= faci * dvdr; + pj->viscosity.div_v -= facj * dvdr; /* Compute dv cross r */ curlvr[0] = dv[1] * dx[2] - dv[2] * dx[1]; curlvr[1] = dv[2] * dx[0] - dv[0] * dx[2]; curlvr[2] = dv[0] * dx[1] - dv[1] * dx[0]; - for (k = 0; k < 3; k++) curlvr[k] *= ri; - - /* Compute density of pi. */ - h_inv = 1.0f / hi; - xi = r * h_inv; - kernel_deval(xi, &wi, &wi_dx); - pi->rho += mj * wi; - pi->rho_dh -= mj * (hydro_dimension * wi + xi * wi_dx); - pi->density.wcount += wi; - pi->density.wcount_dh -= xi * wi_dx; - - pi->density.div_v -= mj * dvdr * wi_dx; - for (k = 0; k < 3; k++) pi->density.rot_v[k] += mj * curlvr[k] * wi_dx; - - /* Compute density of pj. */ - h_inv = 1.0f / hj; - xj = r * h_inv; - kernel_deval(xj, &wj, &wj_dx); - - pj->rho += mi * wj; - pj->rho_dh -= mi * (hydro_dimension * wj + xj * wj_dx); - pj->density.wcount += wj; - pj->density.wcount_dh -= xj * wj_dx; + pi->density.rot_v[0] += faci * curlvr[0]; + pi->density.rot_v[1] += faci * curlvr[1]; + pi->density.rot_v[2] += faci * curlvr[2]; - pj->density.div_v -= mi * dvdr * wj_dx; - for (k = 0; k < 3; k++) pj->density.rot_v[k] += mi * curlvr[k] * wj_dx; + /* Negative because of the change in sign of dx & dv. */ + pj->density.rot_v[0] += facj * curlvr[0]; + pj->density.rot_v[1] += facj * curlvr[1]; + pj->density.rot_v[2] += facj * curlvr[2]; } /** @@ -113,57 +113,157 @@ __attribute__((always_inline)) INLINE static void runner_iact_density( * * @param r2 Comoving square distance between the two particles. * @param dx Comoving vector separating both particles (pi - pj). - * @param hi Comoving smoothing-length of particle i. - * @param hj Comoving smoothing-length of particle j. - * @param pi First particle. - * @param pj Second particle (not updated). + * @param hi Comoving smoothing-length of part*icle i. + * @param hj Comoving smoothing-length of part*icle j. + * @param pi First part*icle. + * @param pj Second part*icle (not updated). * @param a Current scale factor. * @param H Current Hubble parameter. */ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_density( - float r2, const float *dx, float hi, float hj, struct part *restrict pi, - const struct part *restrict pj, float a, float H) { + float r2, const float* dx, float hi, float hj, struct part* pi, + const struct part* pj, float a, float H) { - float r, ri; - float xi; - float h_inv; float wi, wi_dx; - float mj; - float dvdr; float dv[3], curlvr[3]; - int k; /* Get the masses. */ - mj = pj->mass; + const float mj = pj->mass; /* Get r and r inverse. */ - r = sqrtf(r2); - ri = 1.0f / r; + const float r = sqrtf(r2); + + const float h_inv = 1.f / hi; + const float ui = r * h_inv; + kernel_deval(ui, &wi, &wi_dx); + + pi->rho += mj * wi; + pi->density.rho_dh -= mj * (hydro_dimension * wi + ui * wi_dx); + + pi->density.wcount += wi; + pi->density.wcount_dh -= (hydro_dimension * wi + ui * wi_dx); + + const float r_inv = 1.f / r; + const float faci = mj * wi_dx * r_inv; /* Compute dv dot r */ dv[0] = pi->v[0] - pj->v[0]; dv[1] = pi->v[1] - pj->v[1]; dv[2] = pi->v[2] - pj->v[2]; - dvdr = dv[0] * dx[0] + dv[1] * dx[1] + dv[2] * dx[2]; - dvdr *= ri; + const float dvdr = dv[0] * dx[0] + dv[1] * dx[1] + dv[2] * dx[2]; + + pi->viscosity.div_v -= faci * dvdr; /* Compute dv cross r */ curlvr[0] = dv[1] * dx[2] - dv[2] * dx[1]; curlvr[1] = dv[2] * dx[0] - dv[0] * dx[2]; curlvr[2] = dv[0] * dx[1] - dv[1] * dx[0]; - for (k = 0; k < 3; k++) curlvr[k] *= ri; - h_inv = 1.0f / hi; - xi = r * h_inv; - kernel_deval(xi, &wi, &wi_dx); + pi->density.rot_v[0] += faci * curlvr[0]; + pi->density.rot_v[1] += faci * curlvr[1]; + pi->density.rot_v[2] += faci * curlvr[2]; +} - pi->rho += mj * wi; - pi->rho_dh -= mj * (hydro_dimension * wi + xi * wi_dx); - pi->density.wcount += wi; - pi->density.wcount_dh -= xi * wi_dx; +/** + * @brief Calculate the gradient interaction between particle i and particle j + * + * This method wraps around hydro_gradients_collect, which can be an empty + * method, in which case no gradients are used. + * + * @param r2 Comoving squared distance between particle i and particle j. + * @param dx Comoving distance vector between the particles (dx = pi->x - + * pj->x). + * @param hi Comoving smoothing-length of particle i. + * @param hj Comoving smoothing-length of particle j. + * @param pi Particle i. + * @param pj Particle j. + * @param a Current scale factor. + * @param H Current Hubble parameter. + */ +__attribute__((always_inline)) INLINE static void runner_iact_gradient( + float r2, const float* dx, float hi, float hj, struct part* restrict pi, + struct part* restrict pj, float a, float H) { - pi->density.div_v -= mj * dvdr * wi_dx; - for (k = 0; k < 3; k++) pi->density.rot_v[k] += mj * curlvr[k] * wi_dx; + /* We need to construct the maximal signal velocity between our particle + * and all of it's neighbours */ + + const float r = sqrtf(r2); + const float r_inv = 1.f / r; + const float ci = pi->force.soundspeed; + const float cj = pj->force.soundspeed; + + /* Cosmology terms for the signal velocity */ + const float fac_mu = pow_three_gamma_minus_five_over_two(a); + const float a2_Hubble = a * a * H; + + const float dvdr = (pi->v[0] - pj->v[0]) * dx[0] + + (pi->v[1] - pj->v[1]) * dx[1] + + (pi->v[2] - pj->v[2]) * dx[2]; + + /* Add Hubble flow */ + + const float dvdr_Hubble = dvdr + a2_Hubble * r2; + /* Are the particles moving towards each others ? */ + const float omega_ij = min(dvdr_Hubble, 0.f); + const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */ + + /* Signal velocity */ + const float new_v_sig = ci + cj - const_viscosity_beta * mu_ij; + + /* Update if we need to */ + pi->viscosity.v_sig = max(pi->viscosity.v_sig, new_v_sig); + pj->viscosity.v_sig = max(pj->viscosity.v_sig, new_v_sig); +} + +/** + * @brief Calculate the gradient interaction between particle i and particle j: + * non-symmetric version + * + * This method wraps around hydro_gradients_nonsym_collect, which can be an + * empty method, in which case no gradients are used. + * + * @param r2 Comoving squared distance between particle i and particle j. + * @param dx Comoving distance vector between the particles (dx = pi->x - + * pj->x). + * @param hi Comoving smoothing-length of particle i. + * @param hj Comoving smoothing-length of particle j. + * @param pi Particle i. + * @param pj Particle j. + * @param a Current scale factor. + * @param H Current Hubble parameter. + */ +__attribute__((always_inline)) INLINE static void runner_iact_nonsym_gradient( + float r2, const float* dx, float hi, float hj, struct part* restrict pi, + struct part* restrict pj, float a, float H) { + + /* We need to construct the maximal signal velocity between our particle + * and all of it's neighbours */ + + const float r = sqrtf(r2); + const float r_inv = 1.f / r; + const float ci = pi->force.soundspeed; + const float cj = pj->force.soundspeed; + + /* Cosmology terms for the signal velocity */ + const float fac_mu = pow_three_gamma_minus_five_over_two(a); + const float a2_Hubble = a * a * H; + + const float dvdr = (pi->v[0] - pj->v[0]) * dx[0] + + (pi->v[1] - pj->v[1]) * dx[1] + + (pi->v[2] - pj->v[2]) * dx[2]; + + /* Add Hubble flow */ + + const float dvdr_Hubble = dvdr + a2_Hubble * r2; + /* Are the particles moving towards each others ? */ + const float omega_ij = min(dvdr_Hubble, 0.f); + const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */ + + /* Signal velocity */ + const float new_v_sig = ci + cj - const_viscosity_beta * mu_ij; + + /* Update if we need to */ + pi->viscosity.v_sig = max(pi->viscosity.v_sig, new_v_sig); } /** @@ -171,109 +271,129 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_density( * * @param r2 Comoving square distance between the two particles. * @param dx Comoving vector separating both particles (pi - pj). - * @param hi Comoving smoothing-length of particle i. - * @param hj Comoving smoothing-length of particle j. - * @param pi First particle. - * @param pj Second particle. + * @param hi Comoving smoothing-length of part*icle i. + * @param hj Comoving smoothing-length of part*icle j. + * @param pi First part*icle. + * @param pj Second part*icle. * @param a Current scale factor. * @param H Current Hubble parameter. */ __attribute__((always_inline)) INLINE static void runner_iact_force( - float r2, const float *dx, float hi, float hj, struct part *restrict pi, - struct part *restrict pj, float a, float H) { - - float r = sqrtf(r2), ri = 1.0f / r; - float xi, xj; - float hi_inv, hid_inv; - float hj_inv, hjd_inv; - float wi, wj, wi_dx, wj_dx, wi_dr, wj_dr, w, dvdr; - float mi, mj, POrho2i, POrho2j, rhoi, rhoj; - float v_sig, omega_ij, Pi_ij, alpha_ij, tc, v_sig_u; - float f; - int k; + float r2, const float* dx, float hi, float hj, struct part* pi, + struct part* pj, float a, float H) { /* Cosmological factors entering the EoMs */ const float fac_mu = pow_three_gamma_minus_five_over_two(a); const float a2_Hubble = a * a * H; - /* Get some values in local variables. */ - mi = pi->mass; - mj = pj->mass; - rhoi = pi->rho; - rhoj = pj->rho; - POrho2i = pi->force.P_over_rho2; - POrho2j = pj->force.P_over_rho2; + const float r = sqrtf(r2); + const float r_inv = 1.0f / r; + + /* Recover some data */ + const float mj = pj->mass; + const float mi = pi->mass; + + const float rhoi = pi->rho; + const float rhoj = pj->rho; + + const float pressurei = pi->force.pressure; + const float pressurej = pj->force.pressure; /* Get the kernel for hi. */ - hi_inv = 1.0f / hi; - hid_inv = pow_dimension_plus_one(hi_inv); /* 1/h^(d+1) */ - xi = r * hi_inv; + const float hi_inv = 1.0f / hi; + const float hid_inv = pow_dimension_plus_one(hi_inv); /* 1/h^(d+1) */ + const float xi = r * hi_inv; + float wi, wi_dx; kernel_deval(xi, &wi, &wi_dx); - wi_dr = hid_inv * wi_dx; + const float wi_dr = hid_inv * wi_dx; /* Get the kernel for hj. */ - hj_inv = 1.0f / hj; - hjd_inv = pow_dimension_plus_one(hj_inv); /* 1/h^(d+1) */ - xj = r * hj_inv; + const float hj_inv = 1.0f / hj; + const float hjd_inv = pow_dimension_plus_one(hj_inv); /* 1/h^(d+1) */ + const float xj = r * hj_inv; + float wj, wj_dx; kernel_deval(xj, &wj, &wj_dx); - wj_dr = hjd_inv * wj_dx; + const float wj_dr = hjd_inv * wj_dx; /* Compute dv dot r. */ - dvdr = (pi->v[0] - pj->v[0]) * dx[0] + (pi->v[1] - pj->v[1]) * dx[1] + - (pi->v[2] - pj->v[2]) * dx[2] + a2_Hubble * r2; - dvdr *= ri; - - /* Compute the relative velocity. (This is 0 if the particles move away from - * each other and negative otherwise) */ - omega_ij = min(fac_mu * dvdr, 0.f); - - /* Compute signal velocity */ - v_sig = pi->force.soundspeed + pj->force.soundspeed - - const_viscosity_beta * omega_ij; - - /* Compute viscosity parameter */ - alpha_ij = -0.5f * (pi->alpha + pj->alpha); - - /* Compute viscosity tensor */ - Pi_ij = alpha_ij * v_sig * omega_ij / (rhoi + rhoj); - - /* Apply balsara switch */ - Pi_ij *= (pi->force.balsara + pj->force.balsara); - - /* Thermal conductivity */ - v_sig_u = sqrtf(2.f * hydro_gamma_minus_one * - fabs(rhoi * pi->u - rhoj * pj->u) / (rhoi + rhoj)); - tc = pi->alpha_diff * v_sig_u / (rhoi + rhoj); - tc *= (wi_dr + wj_dr); - - /* Get the common factor out. */ - w = ri * - ((POrho2i * wi_dr + POrho2j * wj_dr) + 0.25f * Pi_ij * (wi_dr + wj_dr)); - - /* Use the force, Luke! */ - for (k = 0; k < 3; k++) { - f = dx[k] * w; - pi->a_hydro[k] -= mj * f; - pj->a_hydro[k] += mi * f; - } + const float dvdr = (pi->v[0] - pj->v[0]) * dx[0] + + (pi->v[1] - pj->v[1]) * dx[1] + + (pi->v[2] - pj->v[2]) * dx[2]; + + /* Includes the hubble flow term; not used for du/dt */ + const float dvdr_Hubble = dvdr + a2_Hubble * r2; + + /* Are the particles moving towards each others ? */ + const float omega_ij = min(dvdr_Hubble, 0.f); + const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */ + + /* Compute sound speeds and signal velocity */ + const float v_sig = pi->force.soundspeed + pj->force.soundspeed - + const_viscosity_beta * mu_ij; + + /* Balsara term */ + const float balsara_i = pi->force.balsara; + const float balsara_j = pj->force.balsara; + + /* Construct the full viscosity term */ + /* Balsara includes the alphas */ + const float visc = -0.125f * v_sig * mu_ij * (balsara_i + balsara_j); + + /* Convolve with the kernel */ + const float visc_acc_term = + 0.5f * visc * (wi_dr * pi->force.f / rhoi + wj_dr * pj->force.f / rhoj) * + r_inv; + + /* Compute gradient terms */ + const float P_over_rho2_i = pressurei / (rhoi * rhoi) * pi->force.f; + const float P_over_rho2_j = pressurej / (rhoj * rhoj) * pj->force.f; + + /* SPH acceleration term */ + const float sph_acc_term = + (P_over_rho2_i * wi_dr + P_over_rho2_j * wj_dr) * r_inv; + + /* Assemble the acceleration */ + const float acc = sph_acc_term + visc_acc_term; + + /* Use the force Luke ! */ + pi->a_hydro[0] -= mj * acc * dx[0]; + pi->a_hydro[1] -= mj * acc * dx[1]; + pi->a_hydro[2] -= mj * acc * dx[2]; + + pj->a_hydro[0] += mi * acc * dx[0]; + pj->a_hydro[1] += mi * acc * dx[1]; + pj->a_hydro[2] += mi * acc * dx[2]; /* Get the time derivative for u. */ - pi->force.u_dt += - mj * dvdr * (POrho2i * wi_dr + 0.125f * Pi_ij * (wi_dr + wj_dr)); - pj->force.u_dt += - mi * dvdr * (POrho2j * wj_dr + 0.125f * Pi_ij * (wi_dr + wj_dr)); + const float sph_du_term_i = P_over_rho2_i * dvdr * r_inv * wi_dr; + const float sph_du_term_j = P_over_rho2_j * dvdr * r_inv * wj_dr; - /* Add the thermal conductivity */ - pi->force.u_dt += mj * tc * (pi->u - pj->u); - pj->force.u_dt += mi * tc * (pj->u - pi->u); + /* Viscosity term */ + const float visc_du_term = 0.5f * visc_acc_term * dvdr_Hubble; - /* Get the time derivative for h. */ - pi->force.h_dt -= mj * dvdr / rhoj * wi_dr; - pj->force.h_dt -= mi * dvdr / rhoi * wj_dr; + /* Diffusion term */ + + const float v_diff = + sqrtf(2.0 * fabsf(pressurei - pressurej) / (rhoi + rhoj)) + + dvdr_Hubble * r_inv; + + const float alpha_diff = 0.5f * (pi->diffusion.alpha + pj->diffusion.alpha); + /* wi_dx + wj_dx / 2 is F_ij */ + const float diff_du_term = + alpha_diff * v_diff * (pi->u - pj->u) * 0.5f * + (wi_dr * pi->force.f / pi->rho + wj_dr * pi->force.f / pi->rho); + + /* Assemble the energy equation term */ + const float du_dt_i = sph_du_term_i + visc_du_term + diff_du_term; + const float du_dt_j = sph_du_term_j + visc_du_term - diff_du_term; - /* Update the signal velocity. */ - pi->force.v_sig = max(pi->force.v_sig, v_sig); - pj->force.v_sig = max(pj->force.v_sig, v_sig); + /* Internal energy time derivative */ + pi->u_dt += du_dt_i * mj; + pj->u_dt += du_dt_j * mi; + + /* Get the time derivative for h. */ + pi->force.h_dt -= mj * dvdr * pi->force.f * r_inv / rhoj * wi_dr; + pj->force.h_dt -= mi * dvdr * pj->force.f * r_inv / rhoi * wj_dr; } /** @@ -281,124 +401,162 @@ __attribute__((always_inline)) INLINE static void runner_iact_force( * * @param r2 Comoving square distance between the two particles. * @param dx Comoving vector separating both particles (pi - pj). - * @param hi Comoving smoothing-length of particle i. - * @param hj Comoving smoothing-length of particle j. - * @param pi First particle. - * @param pj Second particle (not updated). + * @param hi Comoving smoothing-length of part*icle i. + * @param hj Comoving smoothing-length of part*icle j. + * @param pi First part*icle. + * @param pj Second part*icle (not updated). * @param a Current scale factor. * @param H Current Hubble parameter. */ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_force( - float r2, const float *dx, float hi, float hj, struct part *restrict pi, - const struct part *restrict pj, float a, float H) { - - float r = sqrtf(r2), ri = 1.0f / r; - float xi, xj; - float hi_inv, hid_inv; - float hj_inv, hjd_inv; - float wi, wj, wi_dx, wj_dx, wi_dr, wj_dr, w, dvdr; - float /*mi,*/ mj, POrho2i, POrho2j, rhoi, rhoj; - float v_sig, omega_ij, Pi_ij, alpha_ij, tc, v_sig_u; - float f; - int k; + float r2, const float* dx, float hi, float hj, struct part* pi, + const struct part* pj, float a, float H) { /* Cosmological factors entering the EoMs */ const float fac_mu = pow_three_gamma_minus_five_over_two(a); const float a2_Hubble = a * a * H; - /* Get some values in local variables. */ - // mi = pi->mass; - mj = pj->mass; - rhoi = pi->rho; - rhoj = pj->rho; - POrho2i = pi->force.P_over_rho2; - POrho2j = pj->force.P_over_rho2; + const float r = sqrtf(r2); + const float r_inv = 1.0f / r; + + /* Recover some data */ + // const float mi = pi->mass; + const float mj = pj->mass; + + const float rhoi = pi->rho; + const float rhoj = pj->rho; + + const float pressurei = pi->force.pressure; + const float pressurej = pj->force.pressure; /* Get the kernel for hi. */ - hi_inv = 1.0f / hi; - hid_inv = pow_dimension_plus_one(hi_inv); /* 1/h^(d+1) */ - xi = r * hi_inv; + const float hi_inv = 1.0f / hi; + const float hid_inv = pow_dimension_plus_one(hi_inv); /* 1/h^(d+1) */ + const float xi = r * hi_inv; + float wi, wi_dx; kernel_deval(xi, &wi, &wi_dx); - wi_dr = hid_inv * wi_dx; + const float wi_dr = hid_inv * wi_dx; /* Get the kernel for hj. */ - hj_inv = 1.0f / hj; - hjd_inv = pow_dimension_plus_one(hj_inv); /* 1/h^(d+1) */ - xj = r * hj_inv; + const float hj_inv = 1.0f / hj; + const float hjd_inv = pow_dimension_plus_one(hj_inv); /* 1/h^(d+1) */ + const float xj = r * hj_inv; + float wj, wj_dx; kernel_deval(xj, &wj, &wj_dx); - wj_dr = hjd_inv * wj_dx; + const float wj_dr = hjd_inv * wj_dx; /* Compute dv dot r. */ - dvdr = (pi->v[0] - pj->v[0]) * dx[0] + (pi->v[1] - pj->v[1]) * dx[1] + - (pi->v[2] - pj->v[2]) * dx[2] + a2_Hubble * r2; - dvdr *= ri; + const float dvdr = (pi->v[0] - pj->v[0]) * dx[0] + + (pi->v[1] - pj->v[1]) * dx[1] + + (pi->v[2] - pj->v[2]) * dx[2]; - /* Compute the relative velocity. (This is 0 if the particles move away from - * each other and negative otherwise) */ - omega_ij = min(fac_mu * dvdr, 0.f); + /* Includes the hubble flow term; not used for du/dt */ + const float dvdr_Hubble = dvdr + a2_Hubble * r2; - /* Compute signal velocity */ - v_sig = pi->force.soundspeed + pj->force.soundspeed - - const_viscosity_beta * omega_ij; + /* Are the particles moving towards each others ? */ + const float omega_ij = min(dvdr_Hubble, 0.f); + const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */ - /* Compute viscosity parameter */ - alpha_ij = -0.5f * (pi->alpha + pj->alpha); + /* Compute sound speeds and signal velocity */ + const float v_sig = pi->force.soundspeed + pj->force.soundspeed - + const_viscosity_beta * mu_ij; - /* Compute viscosity tensor */ - Pi_ij = alpha_ij * v_sig * omega_ij / (rhoi + rhoj); + /* Balsara term */ + const float balsara_i = pi->force.balsara; + const float balsara_j = pj->force.balsara; - /* Apply balsara switch */ - Pi_ij *= (pi->force.balsara + pj->force.balsara); + /* Construct the full viscosity term */ + /* Balsara includes the alphas */ + const float visc = -0.125f * v_sig * mu_ij * (balsara_i + balsara_j); - /* Thermal conductivity */ - v_sig_u = sqrtf(2.f * hydro_gamma_minus_one * - fabs(rhoi * pi->u - rhoj * pj->u) / (rhoi + rhoj)); - tc = pi->alpha_diff * v_sig_u / (rhoi + rhoj); - tc *= (wi_dr + wj_dr); + /* Convolve with the kernel */ + const float visc_acc_term = + 0.5f * visc * (wi_dr * pi->force.f / rhoi + wj_dr * pj->force.f / rhoj) * + r_inv; - /* Get the common factor out. */ - w = ri * - ((POrho2i * wi_dr + POrho2j * wj_dr) + 0.25f * Pi_ij * (wi_dr + wj_dr)); + /* Compute gradient terms */ + const float P_over_rho2_i = pressurei / (rhoi * rhoi) * pi->force.f; + const float P_over_rho2_j = pressurej / (rhoj * rhoj) * pj->force.f; - /* Use the force, Luke! */ - for (k = 0; k < 3; k++) { - f = dx[k] * w; - pi->a_hydro[k] -= mj * f; - } + /* SPH acceleration term */ + const float sph_acc_term = + (P_over_rho2_i * wi_dr + P_over_rho2_j * wj_dr) * r_inv; + + /* Assemble the acceleration */ + const float acc = sph_acc_term + visc_acc_term; + + /* Use the force Luke ! */ + pi->a_hydro[0] -= mj * acc * dx[0]; + pi->a_hydro[1] -= mj * acc * dx[1]; + pi->a_hydro[2] -= mj * acc * dx[2]; /* Get the time derivative for u. */ - pi->force.u_dt += - mj * dvdr * (POrho2i * wi_dr + 0.125f * Pi_ij * (wi_dr + wj_dr)); + const float sph_du_term_i = P_over_rho2_i * dvdr * r_inv * wi_dr; - /* Add the thermal conductivity */ - pi->force.u_dt += mj * tc * (pi->u - pj->u); + /* Viscosity term */ + const float visc_du_term = 0.5f * visc_acc_term * dvdr_Hubble; - /* Get the time derivative for h. */ - pi->force.h_dt -= mj * dvdr / rhoj * wi_dr; + /* Diffusion term */ + const float v_diff = + sqrtf(2.0 * fabsf(pressurei - pressurej) / (rhoi + rhoj)) + + dvdr_Hubble * r_inv; - /* Update the signal velocity. */ - pi->force.v_sig = max(pi->force.v_sig, v_sig); + const float alpha_diff = 0.5f * (pi->diffusion.alpha + pj->diffusion.alpha); + /* wi_dx + wj_dx / 2 is F_ij */ + const float diff_du_term = + alpha_diff * v_diff * (pi->u - pj->u) * 0.5f * + (wi_dr * pi->force.f / pi->rho + wj_dr * pi->force.f / pi->rho); + + /* Assemble the energy equation term */ + const float du_dt_i = sph_du_term_i + visc_du_term + diff_du_term; + + /* Internal energy time derivative */ + pi->u_dt += du_dt_i * mj; + + /* Get the time derivative for h. */ + pi->force.h_dt -= mj * dvdr * pi->force.f * r_inv / rhoj * wi_dr; } /** * @brief Timestep limiter loop + * + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). + * @param hi Comoving smoothing-length of part*icle i. + * @param hj Comoving smoothing-length of part*icle j. + * @param pi First part*icle. + * @param pj Second part*icle (not updated). + * @param a Current scale factor. + * @param H Current Hubble parameter. + * */ __attribute__((always_inline)) INLINE static void runner_iact_limiter( - float r2, const float *dx, float hi, float hj, struct part *restrict pi, - struct part *restrict pj, float a, float H) { + float r2, const float* dx, float hi, float hj, struct part* restrict pi, + struct part* restrict pj, float a, float H) { /* Nothing to do here if both particles are active */ } /** * @brief Timestep limiter loop (non-symmetric version) + * + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). + * @param hi Comoving smoothing-length of part*icle i. + * @param hj Comoving smoothing-length of part*icle j. + * @param pi First part*icle. + * @param pj Second part*icle (not updated). + * @param a Current scale factor. + * @param H Current Hubble parameter. + * */ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_limiter( - float r2, const float *dx, float hi, float hj, struct part *restrict pi, - struct part *restrict pj, float a, float H) { + float r2, const float* dx, float hi, float hj, struct part* restrict pi, + struct part* restrict pj, float a, float H) { /* Wake up the neighbour? */ - if (pi->force.v_sig > const_limiter_max_v_sig_ratio * pj->force.v_sig) { + if (pi->viscosity.v_sig > + const_limiter_max_v_sig_ratio * pj->viscosity.v_sig) { pj->wakeup = time_bin_awake; } diff --git a/src/hydro/Default/hydro_io.h b/src/hydro/Default/hydro_io.h index 858e7e02d8b2ab2a9458f74bb949a5a14faca2cf..7b668fac1700738fb83199900dbb171ac913084f 100644 --- a/src/hydro/Default/hydro_io.h +++ b/src/hydro/Default/hydro_io.h @@ -1,6 +1,7 @@ /******************************************************************************* * This file is part of SWIFT. - * Coypright (c) 2016 Matthieu Schaller (matthieu.schaller@durham.ac.uk) + * Coypright (c) 2019 Josh Borrow (joshua.borrow@durham.ac.uk) & + * Matthieu Schaller (matthieu.schaller@durham.ac.uk) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published @@ -19,6 +20,13 @@ #ifndef SWIFT_DEFAULT_HYDRO_IO_H #define SWIFT_DEFAULT_HYDRO_IO_H +/** + * @file Default/hydro_io.h + * @brief Density-Energy conservative implementation of SPH, + * with added diffusive physics (Cullen & Denhen 2011 AV, + * Price 2017 (PHANTOM) diffusion) (i/o routines) + */ + #include "adiabatic_index.h" #include "hydro.h" #include "io_properties.h" @@ -57,6 +65,7 @@ INLINE static void hydro_read_particles(struct part* parts, list[7] = io_make_input_field("Density", FLOAT, 1, OPTIONAL, UNIT_CONV_DENSITY, parts, rho); } + INLINE static void convert_S(const struct engine* e, const struct part* p, const struct xpart* xp, float* ret) { @@ -122,13 +131,24 @@ INLINE static void convert_part_vel(const struct engine* e, INLINE static void convert_part_potential(const struct engine* e, const struct part* p, const struct xpart* xp, float* ret) { - if (p->gpart != NULL) ret[0] = gravity_get_comoving_potential(p->gpart); else ret[0] = 0.f; } +INLINE static void convert_viscosity(const struct engine* e, + const struct part* p, + const struct xpart* xp, float* ret) { + ret[0] = p->viscosity.alpha; +} + +INLINE static void convert_diffusion(const struct engine* e, + const struct part* p, + const struct xpart* xp, float* ret) { + ret[0] = p->diffusion.alpha; +} + /** * @brief Specifies which particle fields to write to a dataset * @@ -141,7 +161,7 @@ INLINE static void hydro_write_particles(const struct part* parts, struct io_props* list, int* num_fields) { - *num_fields = 10; + *num_fields = 12; /* List what we want to write */ list[0] = io_make_output_field_convert_part("Coordinates", DOUBLE, 3, @@ -159,15 +179,20 @@ INLINE static void hydro_write_particles(const struct part* parts, UNIT_CONV_NO_UNITS, parts, id); list[6] = io_make_output_field("Density", FLOAT, 1, UNIT_CONV_DENSITY, parts, rho); - list[7] = io_make_output_field_convert_part("Entropy", FLOAT, 1, + list[7] = io_make_output_field_convert_part( + "Pressure", FLOAT, 1, UNIT_CONV_PRESSURE, parts, xparts, convert_P); + list[8] = io_make_output_field_convert_part("Entropy", FLOAT, 1, UNIT_CONV_ENTROPY_PER_UNIT_MASS, parts, xparts, convert_S); - list[8] = io_make_output_field_convert_part( - "Pressure", FLOAT, 1, UNIT_CONV_PRESSURE, parts, xparts, convert_P); - - list[0] = io_make_output_field_convert_part("Potential", FLOAT, 1, + list[9] = io_make_output_field_convert_part("Potential", FLOAT, 1, UNIT_CONV_POTENTIAL, parts, xparts, convert_part_potential); + list[10] = io_make_output_field_convert_part("Viscosity", FLOAT, 1, + UNIT_CONV_NO_UNITS, parts, + xparts, convert_viscosity); + list[11] = io_make_output_field_convert_part("Diffusion", FLOAT, 1, + UNIT_CONV_NO_UNITS, parts, + xparts, convert_diffusion); } /** @@ -177,13 +202,11 @@ INLINE static void hydro_write_particles(const struct part* parts, INLINE static void hydro_write_flavour(hid_t h_grpsph) { /* Viscosity and thermal conduction */ + /* Nothing in this minimal model... */ io_write_attribute_s(h_grpsph, "Thermal Conductivity Model", - "Price (2008) without switch"); - - io_write_attribute_s( - h_grpsph, "Viscosity Model", - "Morris & Monaghan (1997), Rosswog, Davies, Thielemann & " - "Piran (2000) with additional Balsara (1995) switch"); + "Simple treatment as in Price (2017)"); + io_write_attribute_s(h_grpsph, "Viscosity Model", + "Simplified version of Cullen & Denhen (2011)"); /* Time integration properties */ io_write_attribute_f(h_grpsph, "Maximal Delta u change over dt", diff --git a/src/hydro/Default/hydro_parameters.h b/src/hydro/Default/hydro_parameters.h index 92010d29442be1cec88eec3caec901f7e38042de..1e492f4a8121dbabb73111e9139df6e8b7cbe6cb 100644 --- a/src/hydro/Default/hydro_parameters.h +++ b/src/hydro/Default/hydro_parameters.h @@ -36,36 +36,50 @@ /** * @file Default/hydro_parameters.h - * @brief Default implementation of SPH (default parameters) + * @brief Density-Energy conservative implementation of SPH, + * with added diffusive physics (Cullen & Denhen 2011 AV, + * Price 2017 (PHANTOM) diffusion) (default compile-time + * parameters). * * This file defines a number of things that are used in * hydro_properties.c as defaults for run-time parameters * as well as a number of compile-time parameters. */ -/* Viscosity parameters -- FIXED -- MUST BE DEFINED AT COMPILE-TIME */ +/*! Viscosity parameters -- FIXED -- MUST BE DEFINED AT COMPILE-TIME */ -/* Cosmology default beta=3.0. +/*! Cosmology default beta=3.0. * Alpha can be set in the parameter file. * Beta is defined as in e.g. Price (2010) Eqn (103) */ #define const_viscosity_beta 3.0f -/* The viscosity that the particles are reset to after being hit by a +/*! The viscosity that the particles are reset to after being hit by a * feedback event. This should be set to the same value as the * hydro_props_default_viscosity_alpha in fixed schemes, and likely * to hydro_props_default_viscosity_alpha_max in variable schemes. */ -#define hydro_props_default_viscosity_alpha_feedback_reset 0.8f +#define hydro_props_default_viscosity_alpha_feedback_reset 2.0f /* Viscosity paramaters -- Defaults; can be changed at run-time */ -/* The "initial" hydro viscosity, or the fixed value for non-variable +/*! The "initial" hydro viscosity, or the fixed value for non-variable * schemes. This usually takes the value 0.8. */ -#define hydro_props_default_viscosity_alpha 0.8f +#define hydro_props_default_viscosity_alpha 0.1f + +/*! Minimal value for the viscosity alpha in variable schemes. */ +#define hydro_props_default_viscosity_alpha_min 0.0f + +/*! Maximal value for the viscosity alpha in variable schemes. */ +#define hydro_props_default_viscosity_alpha_max 2.0f + +/*! Decay length for the viscosity scheme. This is scheme dependent. In + * non-variable schemes this must be defined but is not used. This also + * sets the decay length for the diffusion. */ +#define hydro_props_default_viscosity_length 0.25f /* Diffusion parameters -- Defaults; can be changed at run-time */ -/* The "initial" diffusion, or the fixed value for non-variable - * schemes. This usually takes the value 0.0. */ +/*! The "initial" diffusion, or the fixed value for non-variable + * schemes. For this fixed scheme, this just takes the value of unity. */ #define hydro_props_default_diffusion_alpha 1.0f /* Structs that store the relevant variables */ @@ -75,6 +89,15 @@ struct viscosity_global_data { /*! For the fixed, simple case. Also used to set the initial AV coefficient for variable schemes. */ float alpha; + + /*! Artificial viscosity (max) for the variable case (e.g. M&M) */ + float alpha_max; + + /*! Artificial viscosity (min) for the variable case (e.g. M&M) */ + float alpha_min; + + /*! The decay length of the artificial viscosity (used in M&M, etc.) */ + float length; }; /*! Thermal diffusion parameters */ @@ -113,6 +136,17 @@ static INLINE void viscosity_init(struct swift_params* params, viscosity->alpha = parser_get_opt_param_float( params, "SPH:viscosity_alpha", hydro_props_default_viscosity_alpha); + + viscosity->alpha_max = + parser_get_opt_param_float(params, "SPH:viscosity_alpha_max", + hydro_props_default_viscosity_alpha_max); + + viscosity->alpha_min = + parser_get_opt_param_float(params, "SPH:viscosity_alpha_min", + hydro_props_default_viscosity_alpha_min); + + viscosity->length = parser_get_opt_param_float( + params, "SPH:viscosity_length", hydro_props_default_viscosity_length); } /** @@ -124,6 +158,9 @@ static INLINE void viscosity_init(struct swift_params* params, static INLINE void viscosity_init_no_hydro( struct viscosity_global_data* viscosity) { viscosity->alpha = hydro_props_default_viscosity_alpha; + viscosity->alpha_max = hydro_props_default_viscosity_alpha_max; + viscosity->alpha_min = hydro_props_default_viscosity_alpha_min; + viscosity->length = hydro_props_default_viscosity_length; } /** @@ -134,8 +171,11 @@ static INLINE void viscosity_init_no_hydro( **/ static INLINE void viscosity_print( const struct viscosity_global_data* viscosity) { - message("Artificial viscosity parameters set to alpha: %.3f", - viscosity->alpha); + message( + "Artificial viscosity parameters set to alpha: %.3f, max: %.3f, " + "min: %.3f, length: %.3f.", + viscosity->alpha, viscosity->alpha_max, viscosity->alpha_min, + viscosity->length); } #if defined(HAVE_HDF5) @@ -149,6 +189,10 @@ static INLINE void viscosity_print_snapshot( hid_t h_grpsph, const struct viscosity_global_data* viscosity) { io_write_attribute_f(h_grpsph, "Alpha viscosity", viscosity->alpha); + io_write_attribute_f(h_grpsph, "Alpha viscosity (max)", viscosity->alpha_max); + io_write_attribute_f(h_grpsph, "Alpha viscosity (min)", viscosity->alpha_min); + io_write_attribute_f(h_grpsph, "Viscosity decay length [internal units]", + viscosity->length); io_write_attribute_f(h_grpsph, "Beta viscosity", const_viscosity_beta); } #endif @@ -192,7 +236,7 @@ static INLINE void diffusion_init_no_hydro( **/ static INLINE void diffusion_print( const struct diffusion_global_data* diffusion) { - message("Artificial diffusion parameters set to alpha: %.3f", + message("Artificial diffusion parameters set to alpha: %.3f (fixed).", diffusion->alpha); } diff --git a/src/hydro/Default/hydro_part.h b/src/hydro/Default/hydro_part.h index c262a2db71048858231b9886977b2b8a8f98cf00..e5c8aab4e88dc4f2a6ffe38ea8931e8f7849e5de 100644 --- a/src/hydro/Default/hydro_part.h +++ b/src/hydro/Default/hydro_part.h @@ -1,6 +1,7 @@ /******************************************************************************* * This file is part of SWIFT. - * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk) + * Coypright (c) 2019 Josh Borrow (joshua.borrow@durham.ac.uk) & + * Matthieu Schaller (matthieu.schaller@durham.ac.uk) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published @@ -19,131 +20,180 @@ #ifndef SWIFT_DEFAULT_HYDRO_PART_H #define SWIFT_DEFAULT_HYDRO_PART_H +/** + * @file Default/hydro_part.h + * @brief Density-Energy conservative implementation of SPH, + * with added diffusive physics (Cullen & Denhen 2011 AV, + * Price 2017 (PHANTOM) diffusion) (particle definition) + */ + #include "chemistry_struct.h" #include "cooling_struct.h" #include "star_formation_struct.h" #include "tracers_struct.h" -/* Extra particle data not needed during the SPH loops over neighbours. */ +/** + * @brief Particle fields not needed during the SPH loops over neighbours. + * + * This structure contains the particle fields that are not used in the + * density or force loops. Quantities should be used in the kick, drift and + * potentially ghost tasks only. + */ struct xpart { - /* Offset between current position and position at last tree rebuild. */ + /*! Offset between current position and position at last tree rebuild. */ float x_diff[3]; /*! Offset between the current position and position at the last sort. */ float x_diff_sort[3]; - /* Velocity at the last full step. */ + /*! Velocity at the last full step. */ float v_full[3]; - /* Gravitational acceleration at the last full step. */ + /*! Gravitational acceleration at the last full step. */ float a_grav[3]; - /* Additional data used to record cooling information */ + /*! Internal energy at the last full step. */ + float u_full; + + /*! Additional data used to record cooling information */ struct cooling_xpart_data cooling_data; /* Additional data used by the tracers */ struct tracers_xpart_data tracers_data; - /* Additional data used by the star formation */ + /* Additional data used by the tracers */ struct star_formation_xpart_data sf_data; - float u_full; - - /* Old density. */ - float omega; - } SWIFT_STRUCT_ALIGN; -/* Data of a single particle. */ +/** + * @brief Particle fields for the SPH particles + * + * The density and force substructures are used to contain variables only used + * within the density and force loops over neighbours. All more permanent + * variables should be declared in the main part of the part structure, + */ struct part { - /* Particle ID. */ + /*! Particle unique ID. */ long long id; - /* Pointer to corresponding gravity part. */ + /*! Pointer to corresponding gravity part. */ struct gpart* gpart; - /* Particle position. */ + /*! Particle position. */ double x[3]; - /* Particle predicted velocity. */ + /*! Particle predicted velocity. */ float v[3]; - /* Particle acceleration. */ + /*! Particle acceleration. */ float a_hydro[3]; - /* Particle cutoff radius. */ + /*! Particle mass. */ + float mass; + + /*! Particle smoothing length. */ float h; - /* Particle internal energy. */ + /*! Particle internal energy. */ float u; - /* Particle density. */ + /*! Time derivative of the internal energy. */ + float u_dt; + + /*! Particle density. */ float rho; - /* Derivative of the density with respect to this particle's smoothing length. - */ - float rho_dh; + /* Store viscosity information in a separate struct. */ + struct { + + /*! Particle velocity divergence */ + float div_v; + + /*! Particle velocity divergence from previous step */ + float div_v_previous_step; + + /*! Artificial viscosity parameter */ + float alpha; - /* Particle viscosity parameter */ - float alpha; + /*! Signal velocity */ + float v_sig; - /* Particle diffusion parameter */ - float alpha_diff; + } viscosity; + + /* Store thermal diffusion information in a separate struct. */ + struct { + + /*! del^2 u, a smoothed quantity */ + float laplace_u; + + /*! Thermal diffusion coefficient */ + float alpha; + + } diffusion; /* Store density/force specific stuff. */ union { + /** + * @brief Structure for the variables only used in the density loop over + * neighbours. + * + * Quantities in this sub-structure should only be accessed in the density + * loop over neighbours and the ghost task. + */ struct { - /* Particle velocity divergence. */ - float div_v; + /*! Neighbour number count. */ + float wcount; - /* Derivative of particle number density. */ + /*! Derivative of the neighbour number with respect to h. */ float wcount_dh; - /* Particle velocity curl. */ - float rot_v[3]; + /*! Derivative of density with respect to h */ + float rho_dh; - /* Particle number density. */ - float wcount; + /*! Particle velocity curl. */ + float rot_v[3]; } density; + /** + * @brief Structure for the variables only used in the force loop over + * neighbours. + * + * Quantities in this sub-structure should only be accessed in the force + * loop over neighbours and the ghost, drift and kick tasks. + */ struct { - /* Balsara switch */ - float balsara; - - /* Aggregate quantities. */ - float P_over_rho2; + /*! "Grad h" term -- only partial in P-U */ + float f; - /* Change in particle energy over time. */ - float u_dt; + /*! Particle pressure. */ + float pressure; - /* Signal velocity */ - float v_sig; - - /* Sound speed */ + /*! Particle soundspeed. */ float soundspeed; - /* Change in smoothing length over time. */ + /*! Time derivative of smoothing length */ float h_dt; + /*! Balsara switch */ + float balsara; + } force; }; - /* Particle mass. */ - float mass; - /* Chemistry information */ struct chemistry_part_data chemistry_data; - /* Particle time-bin */ + /*! Time-step length */ timebin_t time_bin; - /* Need waking-up ? */ + /* Need waking up ? */ timebin_t wakeup; #ifdef SWIFT_DEBUG_CHECKS diff --git a/src/hydro/PressureEnergy/hydro_iact.h b/src/hydro/PressureEnergy/hydro_iact.h index e2fc6e7e92423397278f95bd30fb1b3d5d6c93a4..b59fdbbe418d0442fd290b3596fd08531fae88e6 100644 --- a/src/hydro/PressureEnergy/hydro_iact.h +++ b/src/hydro/PressureEnergy/hydro_iact.h @@ -38,10 +38,10 @@ #include "./hydro_parameters.h" /** - * @brief Density interaction between two part*icles. + * @brief Density interaction between two particles. * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. @@ -120,10 +120,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_density( } /** - * @brief Density interaction between two part*icles (non-symmetric). + * @brief Density interaction between two particles (non-symmetric). * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. @@ -180,10 +180,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_density( } /** - * @brief Force interaction between two part*icles. + * @brief Force interaction between two particles. * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. @@ -239,7 +239,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_force( /* Includes the hubble flow term; not used for du/dt */ const float dvdr_Hubble = dvdr + a2_Hubble * r2; - /* Are the part*icles moving towards each others ? */ + /* Are the particles moving towards each others ? */ const float omega_ij = min(dvdr_Hubble, 0.f); const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */ @@ -306,10 +306,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_force( } /** - * @brief Force interaction between two part*icles (non-symmetric). + * @brief Force interaction between two particles (non-symmetric). * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. @@ -366,7 +366,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_force( /* Includes the hubble flow term; not used for du/dt */ const float dvdr_Hubble = dvdr + a2_Hubble * r2; - /* Are the part*icles moving towards each others ? */ + /* Are the particles moving towards each others ? */ const float omega_ij = min(dvdr_Hubble, 0.f); const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */ diff --git a/src/hydro/PressureEnergyMorrisMonaghanAV/hydro_iact.h b/src/hydro/PressureEnergyMorrisMonaghanAV/hydro_iact.h index d7521d3387afc97666e88780aa7894e3a1459b4a..3e0fec0459e7ac17b90d49007c7b38a18f4d8dbc 100644 --- a/src/hydro/PressureEnergyMorrisMonaghanAV/hydro_iact.h +++ b/src/hydro/PressureEnergyMorrisMonaghanAV/hydro_iact.h @@ -39,10 +39,10 @@ #include "./hydro_parameters.h" /** - * @brief Density interaction between two part*icles. + * @brief Density interaction between two particles. * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. @@ -121,10 +121,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_density( } /** - * @brief Density interaction between two part*icles (non-symmetric). + * @brief Density interaction between two particles (non-symmetric). * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. @@ -181,10 +181,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_density( } /** - * @brief Force interaction between two part*icles. + * @brief Force interaction between two particles. * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. @@ -240,7 +240,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_force( /* Includes the hubble flow term; not used for du/dt */ const float dvdr_Hubble = dvdr + a2_Hubble * r2; - /* Are the part*icles moving towards each others ? */ + /* Are the particles moving towards each others ? */ const float omega_ij = min(dvdr_Hubble, 0.f); const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */ @@ -309,10 +309,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_force( } /** - * @brief Force interaction between two part*icles (non-symmetric). + * @brief Force interaction between two particles (non-symmetric). * - * @param r2 Comoving square distance between the two part*icles. - * @param dx Comoving vector separating both part*icles (pi - pj). + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). * @param hi Comoving smoothing-length of part*icle i. * @param hj Comoving smoothing-length of part*icle j. * @param pi First part*icle. @@ -369,7 +369,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_force( /* Includes the hubble flow term; not used for du/dt */ const float dvdr_Hubble = dvdr + a2_Hubble * r2; - /* Are the part*icles moving towards each others ? */ + /* Are the particles moving towards each others ? */ const float omega_ij = min(dvdr_Hubble, 0.f); const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */ diff --git a/src/part.h b/src/part.h index 253cec7b4edad08234a751ee20e6c05fcff7e6ec..820834d652cf53b3dce06192d7c552ec7681f2c7 100644 --- a/src/part.h +++ b/src/part.h @@ -61,6 +61,7 @@ #define hydro_need_extra_init_loop 0 #elif defined(DEFAULT_SPH) #include "./hydro/Default/hydro_part.h" +#define EXTRA_HYDRO_LOOP #define hydro_need_extra_init_loop 0 #elif defined(GIZMO_MFV_SPH) #include "./hydro/GizmoMFV/hydro_part.h" diff --git a/tests/Makefile.am b/tests/Makefile.am index 3407de7588dc297b072567a8b320c99e3ece0462..b75e4ae34a23a6e8c208529345d925a4dcc44623 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -20,9 +20,9 @@ AM_CFLAGS = -I$(top_srcdir)/src $(HDF5_CPPFLAGS) $(GSL_INCS) $(FFTW_INCS) $(NUMA AM_LDFLAGS = ../src/.libs/libswiftsim.a $(HDF5_LDFLAGS) $(HDF5_LIBS) $(FFTW_LIBS) $(NUMA_LIBS) $(TCMALLOC_LIBS) $(JEMALLOC_LIBS) $(TBBMALLOC_LIBS) $(GRACKLE_LIBS) $(GSL_LIBS) $(PROFILER_LIBS) # List of programs and scripts to run in the test suite -TESTS = testGreetings testMaths testReading.sh testSingle testKernel \ +TESTS = testGreetings testMaths testReading.sh testKernel \ testActivePair.sh test27cells.sh test27cellsPerturbed.sh \ - testParser.sh testSPHStep test125cells.sh test125cellsPerturbed.sh testFFT \ + testParser.sh test125cells.sh test125cellsPerturbed.sh testFFT \ testAdiabaticIndex testRandom \ testMatrixInversion testThreadpool testDump testLogger testInteractions.sh \ testVoronoi1D testVoronoi2D testVoronoi3D testGravityDerivatives \ @@ -32,8 +32,8 @@ TESTS = testGreetings testMaths testReading.sh testSingle testKernel \ test27cellsStars.sh test27cellsStarsPerturbed.sh # List of test programs to compile -check_PROGRAMS = testGreetings testReading testSingle testTimeIntegration \ - testSPHStep testActivePair test27cells test27cells_subset test125cells testParser \ +check_PROGRAMS = testGreetings testReading testTimeIntegration \ + testActivePair test27cells test27cells_subset test125cells testParser \ testKernel testFFT testInteractions testMaths testRandom \ testSymmetry testThreadpool \ testAdiabaticIndex testRiemannExact testRiemannTRRS \ @@ -68,10 +68,6 @@ testSymmetry_CFLAGS = $(AM_CFLAGS) -fno-builtin-memcmp testTimeIntegration_SOURCES = testTimeIntegration.c -testSPHStep_SOURCES = testSPHStep.c - -testSingle_SOURCES = testSingle.c - testActivePair_SOURCES = testActivePair.c test27cells_SOURCES = test27cells.c diff --git a/tests/test125cells.c b/tests/test125cells.c index f05d3f83c41b5f26d7828f09aecd76685a5c55b6..725018316c8ff5834e94633a76a7a4a912446aab 100644 --- a/tests/test125cells.c +++ b/tests/test125cells.c @@ -113,7 +113,7 @@ void set_energy_state(struct part *part, enum pressure_field press, float size, part->u = pressure / (hydro_gamma_minus_one * density); #elif defined(MINIMAL_SPH) || defined(HOPKINS_PU_SPH) || \ defined(HOPKINS_PU_SPH_MONAGHAN) || defined(ANARCHY_PU_SPH) || \ - defined(ANARCHY_DU_SPH) + defined(ANARCHY_DU_SPH) || defined(DEFAULT_SPH) part->u = pressure / (hydro_gamma_minus_one * density); #elif defined(PLANETARY_SPH) part->u = pressure / (hydro_gamma_minus_one * density); @@ -402,12 +402,11 @@ void dump_particle_fields(char *fileName, struct cell *main_cell, main_cell->hydro.parts[pid].v[0], main_cell->hydro.parts[pid].v[1], main_cell->hydro.parts[pid].v[2], main_cell->hydro.parts[pid].h, hydro_get_comoving_density(&main_cell->hydro.parts[pid]), -#if defined(MINIMAL_SPH) || defined(PLANETARY_SPH) || \ - defined(GIZMO_MFV_SPH) || defined(SHADOWFAX_SPH) || \ - defined(HOPKINS_PU_SPH) || defined(HOPKINS_PU_SPH_MONAGHAN) || \ - defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH) +#if defined(MINIMAL_SPH) || defined(PLANETARY_SPH) || \ + defined(GIZMO_MFV_SPH) || defined(SHADOWFAX_SPH) || \ + defined(HOPKINS_PU_SPH) || defined(HOPKINS_PU_SPH_MONAGHAN) 0.f, -#elif defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH) +#elif defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH) || defined(DEFAULT_SPH) main_cell->hydro.parts[pid].viscosity.div_v, #else main_cell->hydro.parts[pid].density.div_v, @@ -424,14 +423,11 @@ void dump_particle_fields(char *fileName, struct cell *main_cell, #if defined(GADGET2_SPH) main_cell->hydro.parts[pid].force.v_sig, main_cell->hydro.parts[pid].entropy_dt, 0.f -#elif defined(DEFAULT_SPH) - main_cell->hydro.parts[pid].force.v_sig, 0.f, - main_cell->hydro.parts[pid].force.u_dt #elif defined(MINIMAL_SPH) || defined(HOPKINS_PU_SPH) || \ defined(HOPKINS_PU_SPH_MONAGHAN) main_cell->hydro.parts[pid].force.v_sig, 0.f, main_cell->hydro.parts[pid].u_dt -#elif defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH) +#elif defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH) || defined(DEFAULT_SPH) main_cell->hydro.parts[pid].viscosity.v_sig, 0.f, main_cell->hydro.parts[pid].u_dt #else diff --git a/tests/test27cells.c b/tests/test27cells.c index e7c87cfe76382ed33a36744087e40a9161b60bfa..e403cc1469cb53cdeea5e248bb8b16a301b70e0c 100644 --- a/tests/test27cells.c +++ b/tests/test27cells.c @@ -283,13 +283,13 @@ void dump_particle_fields(char *fileName, struct cell *main_cell, #endif main_cell->hydro.parts[pid].density.wcount, main_cell->hydro.parts[pid].density.wcount_dh, -#if defined(GADGET2_SPH) || defined(DEFAULT_SPH) || defined(HOPKINS_PE_SPH) || \ +#if defined(GADGET2_SPH) || defined(HOPKINS_PE_SPH) || \ defined(HOPKINS_PU_SPH) || defined(HOPKINS_PU_SPH_MONAGHAN) main_cell->hydro.parts[pid].density.div_v, main_cell->hydro.parts[pid].density.rot_v[0], main_cell->hydro.parts[pid].density.rot_v[1], main_cell->hydro.parts[pid].density.rot_v[2] -#elif defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH) +#elif defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH) || defined(DEFAULT_SPH) /* this is required because of the variable AV scheme */ main_cell->hydro.parts[pid].viscosity.div_v, main_cell->hydro.parts[pid].density.rot_v[0], @@ -329,12 +329,12 @@ void dump_particle_fields(char *fileName, struct cell *main_cell, #endif cj->hydro.parts[pjd].density.wcount, cj->hydro.parts[pjd].density.wcount_dh, -#if defined(GADGET2_SPH) || defined(DEFAULT_SPH) || defined(HOPKINS_PE_SPH) +#if defined(GADGET2_SPH) || defined(HOPKINS_PE_SPH) cj->hydro.parts[pjd].density.div_v, cj->hydro.parts[pjd].density.rot_v[0], cj->hydro.parts[pjd].density.rot_v[1], cj->hydro.parts[pjd].density.rot_v[2] -#elif defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH) +#elif defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH) || defined(DEFAULT_SPH) /* this is required because of the variable AV scheme */ cj->hydro.parts[pjd].viscosity.div_v, cj->hydro.parts[pjd].density.rot_v[0], diff --git a/tests/testActivePair.c b/tests/testActivePair.c index 36bc04b6ffc794bcac556f969c0f710e67c4b24b..ef613d5a68b847b6f379c5667447f1de8bf84c58 100644 --- a/tests/testActivePair.c +++ b/tests/testActivePair.c @@ -113,7 +113,7 @@ struct cell *make_cell(size_t n, double *offset, double size, double h, part->entropy = 1.f; #elif defined(MINIMAL_SPH) || defined(HOPKINS_PU_SPH) || \ defined(HOPKINS_PU_SPH_MONAGHAN) || defined(ANARCHY_PU_SPH) || \ - defined(ANARCHY_DU_SPH) + defined(ANARCHY_DU_SPH) || defined(DEFAULT_SPH) part->u = 1.f; #elif defined(HOPKINS_PE_SPH) part->entropy = 1.f; @@ -197,7 +197,7 @@ void zero_particle_fields_force(struct cell *c, const struct cosmology *cosmo, p->density.rot_v[2] = 0.f; p->density.div_v = 0.f; #endif /* GADGET-2 */ -#if defined(MINIMAL_SPH) || defined(ANARCHY_DU_SPH) +#if defined(MINIMAL_SPH) || defined(ANARCHY_DU_SPH) || defined(DEFAULT_SPH) p->rho = 1.f; p->density.rho_dh = 0.f; p->density.wcount = 48.f / (kernel_norm * pow_dimension(p->h)); diff --git a/tests/testInteractions.c b/tests/testInteractions.c index 0b1fb081b89b82223c86836bef6b0f68714eae2a..ef4f0e4c69e7770b032af7c9fb5dc8335fc48c11 100644 --- a/tests/testInteractions.c +++ b/tests/testInteractions.c @@ -114,7 +114,8 @@ void prepare_force(struct part *parts, size_t count) { #if !defined(GIZMO_MFV_SPH) && !defined(SHADOWFAX_SPH) && \ !defined(MINIMAL_SPH) && !defined(PLANETARY_SPH) && \ !defined(HOPKINS_PU_SPH) && !defined(HOPKINS_PU_SPH_MONAGHAN) && \ - !defined(ANARCHY_PU_SPH) && !defined(ANARCHY_DU_SPH) + !defined(ANARCHY_PU_SPH) && !defined(ANARCHY_DU_SPH) && \ + !defined(DEFAULT_SPH) struct part *p; for (size_t i = 0; i < count; ++i) { p = &parts[i]; @@ -141,7 +142,8 @@ void dump_indv_particle_fields(char *fileName, struct part *p) { "%8.5f %8.5f %13e %13e %13e %13e %13e %8.5f %8.5f\n", p->id, p->x[0], p->x[1], p->x[2], p->v[0], p->v[1], p->v[2], p->h, hydro_get_comoving_density(p), -#if defined(MINIMAL_SPH) || defined(PLANETARY_SPH) || defined(SHADOWFAX_SPH) +#if defined(MINIMAL_SPH) || defined(PLANETARY_SPH) || \ + defined(SHADOWFAX_SPH) || defined(DEFAULT_SPH) 0.f, #else p->density.div_v, @@ -156,7 +158,7 @@ void dump_indv_particle_fields(char *fileName, struct part *p) { p->force.v_sig, 0.f, p->force.u_dt #elif defined(MINIMAL_SPH) || defined(HOPKINS_PU_SPH) || \ defined(HOPKINS_PU_SPH_MONAGHAN) || defined(ANARCHY_PU_SPH) || \ - defined(ANARCHY_DU_SPH) + defined(ANARCHY_DU_SPH) || defined(DEFAULT_SPH) p->force.v_sig, 0.f, p->u_dt #else 0.f, 0.f, 0.f diff --git a/tests/testPeriodicBC.c b/tests/testPeriodicBC.c index be83f20a58b17f9a5fdcf967cda9a678aab5b8a9..f19ec46620955d29b73113ddae1ab5680f7e7303 100644 --- a/tests/testPeriodicBC.c +++ b/tests/testPeriodicBC.c @@ -244,11 +244,16 @@ void dump_particle_fields(char *fileName, struct cell *main_cell, int i, int j, #endif main_cell->hydro.parts[pid].density.wcount, main_cell->hydro.parts[pid].density.wcount_dh, -#if defined(GADGET2_SPH) || defined(DEFAULT_SPH) || defined(HOPKINS_PE_SPH) +#if defined(GADGET2_SPH) || defined(HOPKINS_PE_SPH) main_cell->hydro.parts[pid].density.div_v, main_cell->hydro.parts[pid].density.rot_v[0], main_cell->hydro.parts[pid].density.rot_v[1], main_cell->hydro.parts[pid].density.rot_v[2] +#elif defined(DEFAULT_SPH) || defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH) + main_cell->hydro.parts[pid].viscosity.div_v, + main_cell->hydro.parts[pid].density.rot_v[0], + main_cell->hydro.parts[pid].density.rot_v[1], + main_cell->hydro.parts[pid].density.rot_v[2] #else 0., 0., 0., 0. #endif diff --git a/tests/testSPHStep.c b/tests/testSPHStep.c deleted file mode 100644 index 41694872efbfc4d9611127eb1e6324b2b0fa5500..0000000000000000000000000000000000000000 --- a/tests/testSPHStep.c +++ /dev/null @@ -1,221 +0,0 @@ -/******************************************************************************* - * This file is part of SWIFT. - * Copyright (C) 2015 Matthieu Schaller (matthieu.schaller@durham.ac.uk). - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - ******************************************************************************/ - -#include "swift.h" - -#include <stdlib.h> -#include <string.h> - -/** - * @brief Constructs a cell with N SPH particles - */ -struct cell *make_cell(size_t N, float cellSize, int offset[3], int id_offset) { - size_t count = N * N * N; - struct cell *cell = (struct cell *)malloc(sizeof(struct cell)); - bzero(cell, sizeof(struct cell)); - struct part *part; - struct xpart *xpart; - float h; - size_t x, y, z, size; - - size = count * sizeof(struct part); - if (posix_memalign((void **)&cell->hydro.parts, part_align, size) != 0) { - error("couldn't allocate particles"); - } - - size = count * sizeof(struct xpart); - if (posix_memalign((void **)&cell->hydro.xparts, xpart_align, size) != 0) { - error("couldn't allocate extended particles"); - } - - h = 1.2348 * cellSize / N; - - part = cell->hydro.parts; - xpart = cell->hydro.xparts; - memset(part, 0, count * sizeof(struct part)); - memset(xpart, 0, count * sizeof(struct xpart)); - for (x = 0; x < N; ++x) { - for (y = 0; y < N; ++y) { - for (z = 0; z < N; ++z) { - part->x[0] = - offset[0] * cellSize + x * cellSize / N + cellSize / (2 * N); - part->x[1] = - offset[1] * cellSize + y * cellSize / N + cellSize / (2 * N); - part->x[2] = - offset[2] * cellSize + z * cellSize / N + cellSize / (2 * N); - part->h = h; - part->id = x * N * N + y * N + z + id_offset; - part->time_bin = 1; - ++part; - } - } - } - - cell->split = 0; - cell->hydro.h_max = h; - cell->hydro.count = count; - cell->grav.count = 0; - cell->hydro.dx_max_part = 0.; - cell->hydro.dx_max_sort = 0.; - cell->width[0] = cellSize; - cell->width[1] = cellSize; - cell->width[2] = cellSize; - - cell->hydro.ti_end_min = 1; - cell->hydro.ti_end_max = 1; - - cell->hydro.sorted = 0; - for (int k = 0; k < 13; k++) cell->hydro.sort[k] = NULL; - - return cell; -} - -/* Just a forward declaration... */ -void runner_doself1_density(struct runner *r, struct cell *ci); -void runner_doself2_force(struct runner *r, struct cell *ci); -void runner_dopair1_density(struct runner *r, struct cell *ci, struct cell *cj); -void runner_dopair2_force(struct runner *r, struct cell *ci, struct cell *cj); - -/* Run a full time step integration for one cell */ -int main(int argc, char *argv[]) { - -#ifndef DEFAULT_SPH - return 0; -#else - - int i, j, k, offset[3]; - struct part *p; - - int N = 10; - float dim = 1.; - float rho = 2.; - float P = 1.; - - /* Initialize CPU frequency, this also starts time. */ - unsigned long long cpufreq = 0; - clocks_set_cpufreq(cpufreq); - - /* Get some randomness going */ - srand(0); - - /* Create cells */ - struct cell *cells[27]; - for (i = 0; i < 3; i++) - for (j = 0; j < 3; j++) - for (k = 0; k < 3; k++) { - offset[0] = i; - offset[1] = j; - offset[2] = k; - cells[i * 9 + j * 3 + k] = - make_cell(N, dim, offset, (i * 9 + j * 3 + k) * N * N * N); - } - - /* Set particle properties */ - for (j = 0; j < 27; ++j) - for (i = 0; i < cells[j]->hydro.count; ++i) { - cells[j]->hydro.parts[i].mass = dim * dim * dim * rho / (N * N * N); - cells[j]->hydro.parts[i].u = P / (hydro_gamma_minus_one * rho); - } - - message("m=%f", dim * dim * dim * rho / (N * N * N)); - - /* Pick the central cell */ - struct cell *ci = cells[13]; - - /* Create the infrastructure */ - struct space space; - space.periodic = 0; - space.cell_min = 1.; - - struct phys_const prog_const; - prog_const.const_newton_G = 1.f; - - struct hydro_props hp; - hp.target_neighbours = 48.f; - hp.delta_neighbours = 2.; - hp.max_smoothing_iterations = 1; - hp.CFL_condition = 0.1; - - struct engine e; - bzero(&e, sizeof(struct engine)); - e.hydro_properties = &hp; - e.physical_constants = &prog_const; - e.s = &space; - e.time = 0.1f; - e.ti_current = 1; - - struct runner r; - r.e = &e; - - /* Simulation properties */ - e.timeBegin = 0.; - e.timeEnd = 1.; - e.timeOld = 0.; - e.time = 0.1f; - e.ti_current = 1; - - /* The tracked particle */ - p = &(ci->hydro.parts[N * N * N / 2 + N * N / 2 + N / 2]); - - message("Studying particle p->id=%lld", p->id); - - /* Sort the particles */ - for (j = 0; j < 27; ++j) { - runner_do_sort(&r, cells[j], 0x1FFF, 0); - } - - message("Sorting done"); - - /* Initialise the particles */ - for (j = 0; j < 27; ++j) { - runner_do_init(&r, cells[j], 0); - } - - message("Init done"); - - /* Compute density */ - runner_doself1_density(&r, ci); - message("Self done"); - for (int j = 0; j < 27; ++j) - if (cells[j] != ci) runner_dopair1_density(&r, ci, cells[j]); - - message("Density done"); - - /* Ghost task */ - runner_do_ghost(&r, ci); - - message("h=%f rho=%f N_ngb=%f", p->h, p->rho, p->density.wcount); - message("soundspeed=%f", p->force.soundspeed); - - runner_doself2_force(&r, ci); - runner_do_kick(&r, ci, 1); - - message("ti_end=%d", p->ti_end); - - for (int j = 0; j < 27; ++j) { - free(cells[j]->hydro.parts); - free(cells[j]->hydro.xparts); - for (int k = 0; k < 13; k++) - if (cells[j]->hydro.sort[k] != NULL) free(cells[j]->hydro.sort[k]); - free(cells[j]); - } - - return 0; -#endif -} diff --git a/tests/testSingle.c b/tests/testSingle.c deleted file mode 100644 index 52fe51c529b8c3b43f9c5f03fe44b5b742acfc07..0000000000000000000000000000000000000000 --- a/tests/testSingle.c +++ /dev/null @@ -1,147 +0,0 @@ -/******************************************************************************* - * This file is part of SWIFT. - * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk), - * Matthieu Schaller (matthieu.schaller@durham.ac.uk) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - ******************************************************************************/ - -/* Config parameters. */ -#include "../config.h" - -/* Some standard headers. */ -#include <fenv.h> -#include <float.h> -#include <limits.h> -#include <math.h> -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -/* Conditional headers. */ -#ifdef HAVE_LIBZ -#include <zlib.h> -#endif - -/* Local headers. */ -#include "swift.h" - -/* Engine policy flags. */ -#ifndef ENGINE_POLICY -#define ENGINE_POLICY engine_policy_none -#endif - -#ifdef DEFAULT_SPH - -/** - * @brief Main routine that loads a few particles and generates some output. - * - */ - -int main(int argc, char *argv[]) { - - int k, N = 100; - struct part p1, p2; - float x, w, dwdx, r2, dx[3] = {0.0f, 0.0f, 0.0f}, gradw[3]; - - /* Greeting message */ - printf("This is %s\n", package_description()); - - /* Init the particles. */ - for (k = 0; k < 3; k++) { - p1.a_hydro[k] = 0.0f; - p1.v[k] = 0.0f; - p1.x[k] = 0.0; - p2.a_hydro[k] = 0.0f; - p2.v[k] = 0.0f; - p2.x[k] = 0.0; - } - p1.v[0] = 100.0f; - p1.id = 0; - p2.id = 1; - p1.density.wcount = 48.0f; - p2.density.wcount = 48.0f; - p1.rho = 1.0f; - p1.mass = 9.7059e-4; - p1.h = 0.222871287 / 2; - p2.rho = 1.0f; - p2.mass = 9.7059e-4; - p2.h = 0.222871287 / 2; - p1.force.soundspeed = 0.0040824829f; - p1.force.balsara = 0.0f; - p2.force.soundspeed = 58.8972740361f; - p2.force.balsara = 0.0f; - p1.u = 1.e-5 / (hydro_gamma_minus_one * p1.rho); - p2.u = 1.e-5 / (hydro_gamma_minus_one * p2.rho) + 100.0f / (33 * p2.mass); - p1.force.P_over_rho2 = p1.u * hydro_gamma_minus_one / p1.rho; - p2.force.P_over_rho2 = p2.u * hydro_gamma_minus_one / p2.rho; - - /* Dump a header. */ - // printParticle_single(&p1, NULL); - // printParticle_single(&p2, NULL); - printf("# r a_1 udt_1 a_2 udt_2\n"); - - /* Loop over the different radii. */ - for (k = 1; k <= N; k++) { - - /* Set the distance/radius. */ - dx[0] = -((float)k) / N * fmaxf(p1.h, p2.h) * kernel_gamma; - r2 = dx[0] * dx[0]; - - /* Clear the particle fields. */ - p1.a_hydro[0] = 0.0f; - p1.force.u_dt = 0.0f; - p2.a_hydro[0] = 0.0f; - p2.force.u_dt = 0.0f; - - /* Interact the particles. */ - runner_iact_force(r2, dx, p1.h, p2.h, &p1, &p2); - - /* Clear the particle fields. */ - /* p1.rho = 0.0f; p1.density.wcount = 0.0f; - p2.rho = 0.0f; p2.density.wcount = 0.0f; */ - - /* Interact the particles. */ - // runner_iact_density( r2 , dx , p1.h , p2.h , &p1 , &p2 ); - - /* Evaluate just the kernel. */ - x = fabsf(dx[0]) / p1.h; - kernel_deval(x, &w, &dwdx); - gradw[0] = dwdx / (p1.h * p1.h * p1.h * p1.h) * dx[0] / - sqrtf(dx[0] * dx[0] + dx[1] * dx[1] + dx[2] * dx[2]); - gradw[1] = dwdx / (p1.h * p1.h * p1.h * p1.h) * dx[1] / - sqrtf(dx[0] * dx[0] + dx[1] * dx[1] + dx[2] * dx[2]); - gradw[2] = dwdx / (p1.h * p1.h * p1.h * p1.h) * dx[2] / - sqrtf(dx[0] * dx[0] + dx[1] * dx[1] + dx[2] * dx[2]); - - /* Output the results. */ - printf( - "%.3e %.3e %.3e %.3e %.3e %.3e %.3e %.3e %.3e %.3e\n", -dx[0], - p1.a_hydro[0], p1.a_hydro[1], p1.a_hydro[2], p1.force.u_dt, - /// -dx[0] , p1.rho , p1.density.wcount , p2.rho , p2.density.wcount , - w, dwdx, gradw[0], gradw[1], gradw[2]); - - } /* loop over radii. */ - - /* All is calm, all is bright. */ - return 0; -} -#else - -int main(int argc, char *argv[]) { return 0; } - -#endif