/*******************************************************************************
 * This file is part of SWIFT.
 * Copyright (c) 2016 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/>.
 *
 ******************************************************************************/
#ifndef SWIFT_COOLING_PROPERTIES_CHIMES_H
#define SWIFT_COOLING_PROPERTIES_CHIMES_H

/**
 * @file src/cooling/CHIMES/cooling_properties.h
 * @brief Infrastructure for CHIMES cooling.
 */

/* Local includes. */
#include "colibre_tables.h"

enum UV_field_options {
  UV_field_no_UV,        /*!< No UV radiation */
  UV_field_user_defined, /*<! Single user-defined spectrum. */
  UV_field_COLIBRE, /*<! COLIBRE UVB+ISRF (and scale cr_rate and f_dust). */
};

enum UVB_dependence_options {
  UVB_constant,               /*!< Constant UVB. */
  UVB_zdep_cross_secs,        /*!< Redshift-dependent cross sections. */
  UVB_zdep_cross_secs_and_eqm /*!< Redshift-dependent cross sections and eqm
                                 tables */
};

enum Shielding_options {
  Shielding_none,         /*<! No shielding */
  Shielding_Jeans_length, /*<! Jeans length shielding */
  Shielding_COLIBRE,      /*<! COLIBRE shielding length */
};

enum Init_abundance_options {
  init_abundance_single,  /*<! Set each element to the InitIonState param. */
  init_abundance_read,    /*<! Read abundances from eqm abundance tables. */
  init_abundance_compute, /*<! Compute initial equilibrium abundances. */
};

/**
 * @brief Properties of the cooling function.
 * This includes the globalVaraibles structure
 * that holds the parameters used to control
 * the behaviour of the CHIMES module.
 */
struct cooling_function_data {

  /* CHIMES global variables. */
  struct globalVariables ChimesGlobalVars;

  /* Flags to control UV field and shielding options. */
  enum UV_field_options UV_field_choice;
  enum UVB_dependence_options UVB_dependence_choice;
  enum Shielding_options Shielding_choice;

  /* Flag to determine how we set the initial CHIMES abundances. */
  enum Init_abundance_options init_abundance_choice;

  /* User parameter to scale the normalisation of the radiation
   * field by a constant factor. */
  ChimesFloat rad_field_norm_factor;

  /* Factor to re-scale shielding length. */
  double shielding_length_factor;

  /* Maximum shielding length, in kpc.
   * If negative, do not impose a maximum. */
  double max_shielding_length_kpc;

  /* Maximum shielding length, in cm.
   * If negative, do not impose a maximum. */
  double max_shielding_length_cm;

  /* Parameters used for the COLIBRE ISRF. */
  double N_H0;

  /* Parameters that define the maximum shielding length. */
  float lshmax_lowz_kpc;
  float lshmax_highz_kpc;
  float lshmax_transition_redshift;
  float lshmax_transition_width_dz;
  float lshmax_transition_steepness_k;

  /* Parameters that define N_ref. */
  double nref_XH_const;
  double nref_mu_const;
  double nref_column_density_min_cgs;
  double nref_column_density_max_cgs;
  double nref_max_length_kpc;
  double nref_max_length_cgs;
  float nref_trans_temperature_min_K;
  float nref_trans_temperature_max_K;
  float nref_trans_steepness_k;

  /* Parameters that define the cosmic ray rate
   * for UV_field_choice == UV_field_COLIBRE  */
  double cr_rate_at_transition_cgs;
  double cr_transition_column_density_cgs;
  float cr_powerlaw_slope_1;
  float cr_powerlaw_slope_2;
  float cr_cutoff_over_density;
  float cr_cutoff_phys_density_cgs;
  float cr_cutoff_width_dex;
  float cr_cutoff_steepness_k;

  /* Parameters that define the ISRF
   * for UV_field_choice == UV_field_COLIBRE */
  double isrf_norm_at_transition;
  double isrf_transition_column_density_cgs;
  float isrf_powerlaw_slope_1;
  float isrf_powerlaw_slope_2;
  float isrf_cutoff_over_density;
  float isrf_cutoff_phys_density_cgs;
  float isrf_cutoff_width_dex;
  float isrf_cutoff_steepness_k;

  /* Parameter to control use of turbulent Jeans length.
   * Only used with the Colibre shielding mode. */
  int colibre_use_turbulent_jeans_length;

  /* Turbulent 1D velocity dispersion, in km/s. */
  ChimesFloat sigma_turb_km_p_s;

  /* Flags to control eqm mode and thermal evolution. */
  int ChemistryEqmMode;
  int ThermEvolOn;

  /* For init_abundance_mode == read, all elements are initially set to one
   * ionisation state, determined by the InitIonState parameter. */
  int InitIonState;

  /* Cosmic ray ionisation rate of HI (in s^-1). */
  double cosmic_ray_rate;

  /* Temperature of the CMB at present day */
  double T_CMB_0;

  /*! sigma_T * k_B / (m_e * c^2) in internal units */
  double y_compton_factor;

  /* Parameters to compute S and Ca from Si. */
  float S_over_Si_ratio_in_solar;
  float Ca_over_Si_ratio_in_solar;

  float Si_solar_mass_fraction;
  float S_solar_mass_fraction;
  float Ca_solar_mass_fraction;

  /* Solar metallicity */
  float Zsol;

  /* Flag to implement dust depletion as in COLIBRE. */
  int colibre_metal_depletion;

  /* Dust depletion factors in the solar neighbourhood.
   * Taken from Ploeckinger & Schaye. (2020). */
  double f_dust0_C;
  double f_dust0_O;
  double f_dust0_Mg;
  double f_dust0_Si;
  double f_dust0_Ca;
  double f_dust0_Fe;

  /* Distance from EOS to use thermal equilibrium temperature
   * for subgrid props, and to evolve the chemistry in equilibrium. */
  float dlogT_EOS;

  /* Flag to use the subgrid density and
   * temperature from the COLIBRE cooling tables. */
  int use_colibre_subgrid_EOS;

  /* Flag to set particles to chemical equilibrium
   * if they have been heated by feedback. */
  int set_FB_particles_to_eqm;

  /* Threshold to switch between rapid and slow cooling regimes. */
  double rapid_cooling_threshold;

  /* Ionization fraction of gas particles tagged as HII regions */
  float HIIregion_fion;

  /* Temperature of gas particles tagged as HII regions */
  float HIIregion_temp;

  /* Maximum boost factor for reactions on the surfaces
   * of dust grains. */
  float max_dust_boost_factor;

  /* Density below which the dust boost factor is
   * equal to unity, in units of cm^-3. */
  float dust_boost_nH_min_cgs;

  /* Density above which the dust boost factor is
   * equal to the maximum, in units of cm^-3. */
  float dust_boost_nH_max_cgs;

  /* Flag to indicate whether or not we redistribute FB heated
   * particle's dust in the cooling step */
  int destroy_FB_heated_dust;

  /* Array of species names in the reduced
   * CHIMES network. */
  char chimes_species_names_reduced[CHIMES_NETWORK_SIZE]
                                   [CHIMES_NAME_STR_LENGTH];

  /* Colibre cooling table */
  struct colibre_cooling_tables colibre_table;

  /* ------ Physical constants in CGS used internally ------ */

  double boltzmann_k_cgs;
  double proton_mass_cgs;
  double newton_G_cgs;

  double proton_mass_over_boltzmann_k_cgs;

  /* ----- Convertion factors to/from CGS (for quick access) ------ */

  double internal_energy_to_cgs;
  double number_density_to_cgs;
  double density_to_cgs;
  double time_to_cgs;
  double internal_energy_over_time_to_cgs;

  double internal_energy_from_cgs;
  double internal_energy_over_time_from_cgs;
};

#endif /* SWIFT_COOLING_PROPERTIES_CHIMES_H */
