///|
pub fn thermal_energy(temperature : Double) -> Double {
  boltzmann_constant * temperature
}

///|
pub fn thermal_speed(temperature : Double, mass : Double) -> Double {
  thermal_velocity(temperature, mass_kg=mass)
}

///|
pub fn sound_speed_ideal(
  temperature : Double,
  mass : Double,
  gamma : Double,
) -> Double {
  if mass <= 0.0 {
    0.0
  } else {
    (gamma * boltzmann_constant * temperature / mass).sqrt()
  }
}

///|
pub fn alfven_speed(
  magnetic_field : Double,
  density : Double,
  mass : Double,
) -> Double {
  if density <= 0.0 || mass <= 0.0 {
    0.0
  } else {
    magnetic_field.abs() / (vacuum_permittivity * density * mass).sqrt()
  }
}

///|
pub fn magnetic_pressure_si(magnetic_field : Double) -> Double {
  magnetic_field * magnetic_field / (2.0 * vacuum_permittivity)
}

///|
pub fn plasma_beta(
  temperature : Double,
  density : Double,
  magnetic_field : Double,
) -> Double {
  safe_ratio(
    2.0 * density * boltzmann_constant * temperature,
    magnetic_field * magnetic_field / vacuum_permittivity,
    0.0,
  )
}

///|
pub fn thermal_debye_length(
  temperature : Double,
  density : Double,
  charge : Double,
) -> Double {
  let numerator = vacuum_permittivity * boltzmann_constant * temperature
  let denominator = density * charge * charge
  if denominator <= 0.0 {
    0.0
  } else {
    (numerator / denominator).sqrt()
  }
}

///|
pub fn species_plasma_frequency(species : Species, density : Double) -> Double {
  species.plasma_frequency(density)
}

///|
pub fn species_gyro_frequency(species : Species, field : Double) -> Double {
  species.gyro_frequency(field)
}

///|
pub fn species_gyroradius(
  species : Species,
  temperature : Double,
  field : Double,
) -> Double {
  gyroradius(
    species.mass,
    species.thermal_velocity(temperature),
    species.charge,
    field,
  )
}

///|
pub fn plasma_parameter_from_state(
  temperature : Double,
  density : Double,
) -> Double {
  plasma_parameter(density, debye_length(temperature, density))
}

///|
pub fn wave_phase_speed(omega : Double, wave_number : Double) -> Double {
  safe_ratio(omega, wave_number, 0.0)
}

///|
pub fn wave_group_speed(
  omega_first : Double,
  omega_second : Double,
  wave_first : Double,
  wave_second : Double,
) -> Double {
  safe_ratio(omega_second - omega_first, wave_second - wave_first, 0.0)
}

///|
pub fn wavenumber_from_wavelength(wavelength : Double) -> Double {
  safe_ratio(2.0 * pi, wavelength, 0.0)
}

///|
pub fn wavelength_from_wavenumber(wave_number : Double) -> Double {
  safe_ratio(2.0 * pi, wave_number, 0.0)
}

///|
pub fn angular_frequency_from_frequency(frequency : Double) -> Double {
  2.0 * pi * frequency
}

///|
pub fn frequency_from_angular_frequency(angular : Double) -> Double {
  angular / (2.0 * pi)
}

///|
pub fn acoustic_mach(velocity : Double, sound : Double) -> Double {
  safe_ratio(velocity, sound, 0.0)
}

///|
pub fn kinetic_to_thermal_ratio(
  velocity : Double,
  temperature : Double,
  mass : Double,
) -> Double {
  safe_ratio(0.5 * mass * velocity * velocity, thermal_energy(temperature), 0.0)
}

///|
pub fn dimensionless_time(time : Double, frequency : Double) -> Double {
  time * frequency
}

///|
pub fn dimensionless_length(length : Double, scale : Double) -> Double {
  safe_ratio(length, scale, 0.0)
}

///|
pub fn normalize_wave_number(wave_number : Double, debye : Double) -> Double {
  wave_number * debye
}

///|
pub fn estimate_landau_rate(
  wave_number : Double,
  temperature : Double,
  density : Double,
) -> Double {
  landau_damping_rate(wave_number, temperature, density)
}