/*******************************************************************************
* This file is part of SWIFT.
* Copyright (c) 2021 Willem Elbers (willem.h.elbers@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_DEFAULT_NEUTRINO_H
#define SWIFT_DEFAULT_NEUTRINO_H
/* Config parameters. */
#include
/* Local includes */
#include "../../engine.h"
#include "fermi_dirac.h"
#include "neutrino_properties.h"
#include "neutrino_response.h"
#include "relativity.h"
/* Riemann function zeta(3) */
#define M_ZETA_3 1.2020569031595942853997
/**
* @brief Shared information for delta-f neutrino weighting of a cell.
*/
struct neutrino_model {
char use_delta_f_mesh_only;
double *M_nu_eV;
double *deg_nu;
int N_nu;
double fac;
double inv_mass_factor;
long long neutrino_seed;
};
void gather_neutrino_consts(const struct space *s, struct neutrino_model *nm);
void gpart_neutrino_weight_mesh_only(const struct gpart *gp,
const struct neutrino_model *nm,
double *weight);
void gpart_neutrino_mass_weight(const struct gpart *gp,
const struct neutrino_model *nm, double *mass,
double *weight);
/* Compute the ratio of macro particle mass in internal mass units to
* the mass of one microscopic neutrino in eV.
*
* @param cosmo The #cosmology used for this run.
* @param internal_units The system of units used internally.
* @param physical_constants The #phys_const used for this run.
* @param volume The volume occupied by neutrino particles
* @param nr_nuparts The number of macro neutrino particles
*/
INLINE static double neutrino_mass_factor(
const struct cosmology *cosmo, const struct unit_system *internal_units,
const struct phys_const *physical_constants, double volume,
double nr_nuparts) {
/* Some constants */
const double k_b = physical_constants->const_boltzmann_k;
const double hbar = physical_constants->const_planck_hbar;
const double c = physical_constants->const_speed_light_c;
const double eV = physical_constants->const_electron_volt;
const double eV_mass = eV / (c * c); // 1 eV/c^2 in internal mass units
const double prefactor = (1.5 * M_ZETA_3) / (M_PI * M_PI);
const double T_nu = cosmo->T_nu_0;
const int N_nu = cosmo->N_nu;
/* Compute the comoving number density per flavour */
const double kThc = k_b * T_nu / (hbar * c);
const double n = prefactor * kThc * kThc * kThc;
/* Compute the conversion factor per flavour */
const double mass_factor = nr_nuparts / (n * volume * N_nu);
/* Convert to eV */
const double mass_factor_eV = mass_factor / eV_mass;
return mass_factor_eV;
}
/**
* @brief Initialises the neutrino g-particles for the first time. This is done
* in addition to gravity_first_init_gpart().
*
* This function is called only once just after the ICs have been read in
* and after IDs have been remapped (if used) by space_remap_ids().
*
* @param gp The particle to act upon
* @param engine The engine of the run
*/
__attribute__((always_inline)) INLINE static void gravity_first_init_neutrino(
struct gpart *gp, const struct engine *e) {
/* Do we need to do anything? */
if (!e->neutrino_properties->generate_ics) return;
/* Retrieve physical and cosmological constants */
const double c_vel = e->physical_constants->const_speed_light_c;
const double *m_eV_array = e->cosmology->M_nu_eV;
const double *deg_array = e->cosmology->deg_nu;
const int N_nu = e->cosmology->N_nu;
const double T_eV = e->cosmology->T_nu_0_eV;
const double inv_fac = c_vel * T_eV;
const double inv_mass_factor = 1. / e->neutrino_mass_conversion_factor;
const long long neutrino_seed = e->neutrino_properties->neutrino_seed;
/* Use a particle id dependent seed */
const long long seed = gp->id_or_neg_offset + neutrino_seed;
/* Compute the initial dimensionless momentum from the seed */
const double pi = neutrino_seed_to_fermi_dirac(seed);
/* The neutrino mass and degeneracy (we cycle based on the neutrino seed) */
const double m_eV = neutrino_seed_to_mass(N_nu, m_eV_array, seed);
const double deg = neutrino_seed_to_degeneracy(N_nu, deg_array, seed);
/* Compute the initial direction of the momentum vector from the seed */
double n[3];
neutrino_seed_to_direction(seed, n);
/* Set the initial velocity */
const double vi = pi * inv_fac / m_eV;
gp->v_full[0] = n[0] * vi;
gp->v_full[1] = n[1] * vi;
gp->v_full[2] = n[2] * vi;
/* If running with the delta-f method, set the weight to (almost) zero */
if (e->neutrino_properties->use_delta_f) {
gp->mass = FLT_MIN;
}
/* Otherwise, set the mass based on the mass factor */
else {
gp->mass = deg * m_eV * inv_mass_factor;
}
}
void compute_neutrino_diagnostics(
const struct space *s, const struct cosmology *cosmo,
const struct phys_const *physical_constants,
const struct neutrino_props *neutrino_properties, const int rank, double *r,
double *I_df, double *mass_tot);
void neutrino_check_cosmology(const struct space *s,
const struct cosmology *cosmo,
const struct phys_const *physical_constants,
struct swift_params *params,
const struct neutrino_props *neutrino_props,
const int rank, const int verbose);
double lightcone_map_neutrino_baseline_value(
const struct cosmology *c, const struct lightcone_props *lightcone_props,
const struct lightcone_map *map);
#endif /* SWIFT_DEFAULT_NEUTRINO_H */