/******************************************************************************* * This file is part of SWIFT. * Copyright (c) 2023 Matthieu Schaller (schaller@strw.leidenuniv.nl) * 2025 Thomas Sandnes (thomas.d.sandnes@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 . * ******************************************************************************/ #ifndef SWIFT_FORCING_BOUNDARY_PARTICLES_H #define SWIFT_FORCING_BOUNDARY_PARTICLES_H /* Config parameters. */ #include /* Standard includes. */ #include /* Local includes. */ #include "engine.h" #include "error.h" #include "parser.h" #include "part.h" #include "physical_constants.h" #include "space.h" #include "units.h" /** * @brief Forcing Term Properties */ struct forcing_terms { /*! Particles with ID <= boundary_particle_max_id are treated as boundary * particles. */ int boundary_particle_max_id; /*! Whether or not boundary particles are fixed in place (0 (false, default) * or 1 (true)) */ int enable_fixed_position; /*! Whether or not boundary particles have hydrodynamic accelerations enabled * (0 (false, default) or 1 (true)) */ int enable_hydro_acceleration; /*! Whether or not boundary particles have gravitational accelerations enabled * (0 (false, default) or 1 (true)) */ int enable_grav_acceleration; }; /** * @brief Computes the hydrodynamic forcing terms. * * Resets the hydrodynamic accelerations of boundary particles to zero. * If using fixed boundary particles, their velocities are also set to zero. * * @param time The current time. * @param terms The properties of the forcing terms. * @param s The #space we act on. * @param phys_const The physical constants in internal units. * @param p Pointer to the particle data. * @param xp Pointer to the extended particle data. */ __attribute__((always_inline)) INLINE static void forcing_hydro_terms_apply( const double time, const struct forcing_terms *terms, const struct space *s, const struct phys_const *phys_const, struct part *p, struct xpart *xp) { if (terms->enable_hydro_acceleration) { /* Skip if not resetting hydro accelerations. */ return; } if (p->id <= terms->boundary_particle_max_id) { /* Reset the hydro accelerations of boundary particles. */ p->a_hydro[0] = 0.0f; p->a_hydro[1] = 0.0f; p->a_hydro[2] = 0.0f; #if defined(GIZMO_MFV_SPH) || defined(GIZMO_MFM_SPH) /* Some values need to be reset in the Gizmo case. */ hydro_prepare_force(p, &c->hydro.xparts[k], cosmo, e->hydro_properties, e->pressure_floor_props, /*dt_alpha=*/0, /*dt_therm=*/0); rt_prepare_force(p); #endif if (terms->enable_fixed_position) { /* Set velocity of fixed boundary particle to zero. */ xp->v_full[0] = 0.f; xp->v_full[1] = 0.f; xp->v_full[2] = 0.f; } } } /** * @brief Computes the gravitational forcing terms. * * Resets the gravitational accelerations of boundary particles to zero. * If using fixed boundary particles, their velocities are also set to zero. * * @param id The particle ID. * @param terms The properties of the forcing terms. * @param gp Pointer to the particle data. */ __attribute__((always_inline)) INLINE static void forcing_grav_terms_apply( const long long id, const struct forcing_terms *terms, struct gpart *gp) { if (terms->enable_grav_acceleration) { /* Skip if not resetting grav accelerations. */ return; } if (id <= terms->boundary_particle_max_id) { /* Reset the grav accelerations of boundary particles. */ gp->a_grav[0] = 0.0f; gp->a_grav[1] = 0.0f; gp->a_grav[2] = 0.0f; if (terms->enable_fixed_position) { /* Set velocity of fixed boundary particle to zero. */ gp->v_full[0] = 0.f; gp->v_full[1] = 0.f; gp->v_full[2] = 0.f; } } } /** * @brief Sets the forcing of gparts prior to drift. * * Resets the velocities of fixed boundary particles to zero. * * @param id The particle ID. * @param terms The properties of the forcing terms. * @param gp Pointer to the particle data. */ __attribute__((always_inline)) INLINE static void forcing_gpart_drift_apply( const long long id, const struct forcing_terms *terms, struct gpart *gp) { if (id <= terms->boundary_particle_max_id && terms->enable_fixed_position) { /* Set velocity of fixed boundary particle to zero. */ gp->v_full[0] = 0.f; gp->v_full[1] = 0.f; gp->v_full[2] = 0.f; } } /** * @brief Sets the forcing of parts prior to drift. * * Resets the velocities of fixed boundary particles to zero. * * @param id The particle ID. * @param terms The properties of the forcing terms. * @param p Pointer to the particle data. * @param xp Pointer to the extended particle data. */ __attribute__((always_inline)) INLINE static void forcing_part_drift_apply( const long long id, const struct forcing_terms *terms, struct part *p, struct xpart *xp) { if (id <= terms->boundary_particle_max_id && terms->enable_fixed_position) { /* Set velocity of fixed boundary particle to zero. */ xp->v_full[0] = 0.f; xp->v_full[1] = 0.f; xp->v_full[2] = 0.f; } } /** * @brief Sets the forcing of sparts prior to drift. * * Resets the velocities of fixed boundary particles to zero. * * @param id The particle ID. * @param terms The properties of the forcing terms. * @param sp Pointer to the particle data. */ __attribute__((always_inline)) INLINE static void forcing_spart_drift_apply( const long long id, const struct forcing_terms *terms, struct spart *sp) { if (id <= terms->boundary_particle_max_id && terms->enable_fixed_position) { /* Set velocity of fixed boundary particle to zero. */ sp->v[0] = 0.f; sp->v[1] = 0.f; sp->v[2] = 0.f; } } /** * @brief Sets the forcing of bparts prior to drift. * * Resets the velocities of fixed boundary particles to zero. * * @param id The particle ID. * @param terms The properties of the forcing terms. * @param bp Pointer to the particle data. */ __attribute__((always_inline)) INLINE static void forcing_bpart_drift_apply( const long long id, const struct forcing_terms *terms, struct bpart *bp) { if (id <= terms->boundary_particle_max_id && terms->enable_fixed_position) { /* Set velocity of fixed boundary particle to zero. */ bp->v[0] = 0.f; bp->v[1] = 0.f; bp->v[2] = 0.f; } } /** * @brief Computes the time-step condition due to the forcing terms. * * Nothing to do here. --> Return FLT_MAX. * * @param time The current time. * @param terms The properties of the forcing terms. * @param phys_const The physical constants in internal units. * @param p Pointer to the particle data. * @param xp Pointer to the extended particle data. */ __attribute__((always_inline)) INLINE static float forcing_terms_timestep( double time, const struct forcing_terms *terms, const struct phys_const *phys_const, const struct part *p, const struct xpart *xp) { return FLT_MAX; } /** * @brief Prints the properties of the forcing terms to stdout. * * @param terms The #forcing_terms properties of the run. */ static INLINE void forcing_terms_print(const struct forcing_terms *terms) { message( "Forcing terms is 'Boundary particles'. Max boundary particle ID: %i.", terms->boundary_particle_max_id); message( "Run with options: Enable fixed position: %i, Enable hydro acceleration: " "%i, Enable grav acceleration: %i", terms->enable_fixed_position, terms->enable_hydro_acceleration, terms->enable_grav_acceleration); } /** * @brief Initialises the forcing term properties * * @param parameter_file The parsed parameter file * @param phys_const Physical constants in internal units * @param us The current internal system of units * @param s The #space object. * @param terms The forcing term properties to initialize */ static INLINE void forcing_terms_init(struct swift_params *parameter_file, const struct phys_const *phys_const, const struct unit_system *us, const struct space *s, struct forcing_terms *terms) { terms->boundary_particle_max_id = parser_get_param_int( parameter_file, "BoundaryParticles:boundary_particle_max_id"); terms->enable_fixed_position = parser_get_opt_param_int( parameter_file, "BoundaryParticles:enable_fixed_position", 0); terms->enable_hydro_acceleration = parser_get_opt_param_int( parameter_file, "BoundaryParticles:enable_hydro_acceleration", 0); terms->enable_grav_acceleration = parser_get_opt_param_int( parameter_file, "BoundaryParticles:enable_grav_acceleration", 0); if (terms->enable_fixed_position != 0 && terms->enable_fixed_position != 1) { error( "BoundaryParticles:enable_fixed_position must be either 0 (false) or 1 " "(true)."); } if (terms->enable_fixed_position) { /* If using fixed boundary particles, both hydro and grav accelerations must * be reset to 0. */ if (terms->enable_hydro_acceleration != 0) { error( "BoundaryParticles:enable_hydro_acceleration must be 0 (false) when " "using fixed boundary particles."); } if (terms->enable_grav_acceleration != 0) { error( "BoundaryParticles:enable_grav_acceleration must be 0 (false) when " "using fixed boundary particles."); } } else { /* If not using fixed boundary particles, hydro and grav accelerations can * be enabled independently. */ if (terms->enable_hydro_acceleration != 0 && terms->enable_hydro_acceleration != 1) { error( "BoundaryParticles:enable_hydro_acceleration must be either 0 " "(false) or 1 (true)."); } if (terms->enable_grav_acceleration != 0 && terms->enable_grav_acceleration != 1) { error( "BoundaryParticles:enable_grav_acceleration must be either 0 (false) " "or 1 (true)."); } } } #endif /* SWIFT_FORCING_BOUNDARY_PARTICLES_H */