#[repr(C)]
#[derive(Default, Clone, Copy)]
pub struct Composition {
pub methane: f64,
pub nitrogen: f64,
pub carbon_dioxide: f64,
pub ethane: f64,
pub propane: f64,
pub isobutane: f64,
pub n_butane: f64,
pub isopentane: f64,
pub n_pentane: f64,
pub hexane: f64,
pub heptane: f64,
pub octane: f64,
pub nonane: f64,
pub decane: f64,
pub hydrogen: f64,
pub oxygen: f64,
pub carbon_monoxide: f64,
pub water: f64,
pub hydrogen_sulfide: f64,
pub helium: f64,
pub argon: f64,
}
impl Composition {
pub fn sum(&self) -> f64 {
self.methane
+ self.nitrogen
+ self.carbon_dioxide
+ self.ethane
+ self.propane
+ self.isobutane
+ self.n_butane
+ self.isopentane
+ self.n_pentane
+ self.hexane
+ self.heptane
+ self.octane
+ self.nonane
+ self.decane
+ self.hydrogen
+ self.oxygen
+ self.carbon_monoxide
+ self.water
+ self.hydrogen_sulfide
+ self.helium
+ self.argon
}
pub fn normalize(&mut self) -> Result<(), CompositionError> {
let sum = self.sum();
if sum > 0.0 {
let factor = 1.0 / sum;
self.methane *= factor;
self.nitrogen *= factor;
self.carbon_dioxide *= factor;
self.ethane *= factor;
self.propane *= factor;
self.isobutane *= factor;
self.n_butane *= factor;
self.isopentane *= factor;
self.n_pentane *= factor;
self.hexane *= factor;
self.heptane *= factor;
self.octane *= factor;
self.nonane *= factor;
self.decane *= factor;
self.hydrogen *= factor;
self.oxygen *= factor;
self.carbon_monoxide *= factor;
self.water *= factor;
self.hydrogen_sulfide *= factor;
self.helium *= factor;
self.argon *= factor;
} else {
return Err(CompositionError::Empty);
}
Ok(())
}
pub fn check(&self) -> Result<(), CompositionError> {
if (self.sum() - 0.0).abs() < 1.0e-10 {
return Err(CompositionError::Empty);
}
if (self.sum() - 1.0).abs() > 1.0e-2 {
return Err(CompositionError::BadSum);
}
Ok(())
}
}
#[repr(C)]
#[derive(Debug, PartialEq, Eq)]
pub enum CompositionError {
Ok = 0,
Empty,
BadSum,
}
#[cfg(test)]
mod tests {
use super::*;
const COMP_FULL: Composition = Composition {
methane: 0.778_24,
nitrogen: 0.02,
carbon_dioxide: 0.06,
ethane: 0.08,
propane: 0.03,
isobutane: 0.001_5,
n_butane: 0.003,
isopentane: 0.000_5,
n_pentane: 0.001_65,
hexane: 0.002_15,
heptane: 0.000_88,
octane: 0.000_24,
nonane: 0.000_15,
decane: 0.000_09,
hydrogen: 0.004,
oxygen: 0.005,
carbon_monoxide: 0.002,
water: 0.000_1,
hydrogen_sulfide: 0.002_5,
helium: 0.007,
argon: 0.001,
};
#[test]
fn valid_is_ok() {
let comp = Composition {
methane: 0.5,
ethane: 0.5,
..Default::default()
};
assert_eq!(comp.check(), Ok(()));
}
#[test]
fn empty_is_error() {
let comp = Composition {
..Default::default()
};
assert_eq!(comp.check(), Err(CompositionError::Empty));
}
#[test]
fn too_big_is_error() {
let comp = Composition {
ethane: 0.5,
methane: 0.6,
propane: 0.4,
..Default::default()
};
assert_eq!(comp.check(), Err(CompositionError::BadSum));
}
#[test]
fn normalized_is_1() {
let mut comp = COMP_FULL;
comp.normalize().unwrap();
assert_eq!(comp.sum(), 1.0);
}
#[test]
fn normalize_empty_is_error() {
let mut comp = Composition {
..Default::default()
};
assert_eq!(comp.normalize(), Err(CompositionError::Empty));
}
#[test]
fn clone_gas_comp() {
let mut gas_comp = Composition {
argon: 50.0,
methane: 50.0,
..Default::default()
};
let mut gas_comp_clone = gas_comp.clone();
gas_comp.argon = 0.0;
gas_comp_clone.normalize().unwrap();
assert_eq!(gas_comp_clone.argon, 0.5);
}
#[test]
fn copy_gas_comp() {
let gas_comp = Composition {
argon: 50.0,
methane: 50.0,
..Default::default()
};
let mut gas_comp_clone = gas_comp;
gas_comp_clone.normalize().unwrap();
assert_eq!(gas_comp_clone.argon, 0.5);
}
}