///|
pub(all) struct Species {
  name : String
  charge : Double
  mass : Double
} derive(Debug, ToJson)

///|
pub fn Species::electron() -> Species {
  { name: "electron", charge: -elementary_charge, mass: electron_mass }
}

///|
pub fn Species::proton() -> Species {
  { name: "proton", charge: elementary_charge, mass: proton_mass }
}

///|
pub fn Species::ion(
  name : String,
  charge_state : Int,
  mass_kg : Double,
) -> Species {
  { name, charge: charge_state.to_double() * elementary_charge, mass: mass_kg }
}

///|
pub fn Species::plasma_frequency(
  species : Species,
  density_m3 : Double,
) -> Double {
  plasma_frequency(
    density_m3,
    charge_c=species.charge.abs(),
    mass_kg=species.mass,
  )
}

///|
pub fn Species::thermal_velocity(
  species : Species,
  temperature_k : Double,
) -> Double {
  thermal_velocity(temperature_k, mass_kg=species.mass)
}

///|
pub fn Species::gyro_frequency(
  species : Species,
  magnetic_field_t : Double,
) -> Double {
  gyro_frequency(species.charge, magnetic_field_t, species.mass)
}

///|
pub fn particle_for_species(
  species : Species,
  x~ : Double,
  v~ : Double,
  weight? : Double = 1.0,
) -> Particle {
  Particle::new(x~, v~, weight~, charge=species.charge, mass=species.mass)
}