diff --git a/src/properties/thermo_db.rs b/src/properties/thermo_db.rs index dc91b8e..d854d72 100644 --- a/src/properties/thermo_db.rs +++ b/src/properties/thermo_db.rs @@ -4,7 +4,7 @@ use crate::properties::{ polynomials::{Phase, Polynomial, SpeciesElement, SpeciesPolynomial}, }; -fn parse_fields<'a>(line: &'a str, widths: &[usize]) -> Vec { +fn parse_fields(line: &str, widths: &[usize]) -> Vec { let mut fields = Vec::new(); let mut pos = 0; @@ -44,72 +44,73 @@ impl ThermoDB { // Parse species block if species_block { - species.push(Self::parse_species(&mut lines)?); + species.push(parse_species(&mut lines)?); } //TODO Distinguish between products and reactants } todo!() } +} - fn parse_species<'a>( - lines: &mut impl Iterator, - ) -> Result { - // Parsing a fortran generated file which means we used fixed column width parsing. Define the - // fixed column widths used - const SPECIES_LINE_2_WIDTHS: &[usize] = &[3, 7, 2, 6, 2, 6, 2, 6, 2, 6, 2, 6, 2, 13, 15]; +fn parse_species<'a>( + lines: &mut impl Iterator, +) -> Result { + // Parsing a fortran generated file which means we used fixed column width parsing. Define the + // fixed column widths used + const SPECIES_LINE_2_WIDTHS: &[usize] = &[3, 7, 2, 6, 2, 6, 2, 6, 2, 6, 2, 6, 2, 13, 15]; - let line = lines.next().ok_or(PropertiesError::InvalidFile)?; - let name = line - .get(0..16) - .ok_or(PropertiesError::InvalidLine("name".to_string()))? - .to_string(); + let line = lines.next().ok_or(PropertiesError::InvalidFile)?; + let name = line + .get(0..16) + .ok_or(PropertiesError::InvalidLine("name".to_string()))? + .trim() + .to_string(); - // line 2 - let line = lines.next().ok_or(PropertiesError::InvalidFile)?; - let split = parse_fields(line, SPECIES_LINE_2_WIDTHS); - let intervals: usize = split[0] + // line 2 + let line = lines.next().ok_or(PropertiesError::InvalidFile)?; + let split = parse_fields(line, SPECIES_LINE_2_WIDTHS); + let intervals: usize = split[0] + .parse() + .map_err(|_| make_parse_error("intervals", "usize", &split[0]))?; + + let mut elements = vec![]; + for i in (2..=10).step_by(2) { + let element = split[i].to_string(); + let count: f64 = split[i + 1] .parse() - .map_err(|_| make_parse_error("intervals", "usize", &split[0]))?; + .map_err(|_| make_parse_error("species_count", "f64", &split[i + 1]))?; - let mut elements = vec![]; - for i in (2..=10).step_by(2) { - let element = split[i].to_string(); - let count: f64 = split[i + 1] - .parse() - .map_err(|_| make_parse_error("species_count", "f64", &split[i + 1]))?; - - if count.abs() > 1e-8 { - elements.push(SpeciesElement { element, count }) - } + if count.abs() > 1e-8 { + elements.push(SpeciesElement { element, count }) } - - let phase = match split[12] - .parse::() - .map_err(|_| make_parse_error("phase", "i32", &split[12]))? - { - 0 => Phase::Gas, - _ => Phase::Condensed, - }; - - let molecular_weight = split[13] - .parse() - .map_err(|_| make_parse_error("molecular_weight", "f64", &split[13]))?; - - let h_formation = split[14] - .parse() - .map_err(|_| make_parse_error("h_formation", "f64", &split[14]))?; - - let polynomials = parse_polynomials_block(lines, intervals)?; - - Ok(SpeciesPolynomial { - name, - polynomials, - elements, - phase, - molecular_weight, - h_formation, - }) } + + let phase = match split[12] + .parse::() + .map_err(|_| make_parse_error("phase", "i32", &split[12]))? + { + 0 => Phase::Gas, + _ => Phase::Condensed, + }; + + let molecular_weight = split[13] + .parse() + .map_err(|_| make_parse_error("molecular_weight", "f64", &split[13]))?; + + let h_formation = split[14] + .parse() + .map_err(|_| make_parse_error("h_formation", "f64", &split[14]))?; + + let polynomials = parse_polynomials_block(lines, intervals)?; + + Ok(SpeciesPolynomial { + name, + polynomials, + elements, + phase, + molecular_weight, + h_formation, + }) } fn parse_polynomials_block<'a>( @@ -167,7 +168,13 @@ fn parse_polynomial_block<'a>( #[cfg(test)] mod test { - use crate::{assert_delta, assert_vec_delta, properties::thermo_db::parse_polynomial_block}; + use crate::{ + assert_delta, assert_vec_delta, + properties::{ + polynomials::Phase, + thermo_db::{parse_polynomial_block, parse_polynomials_block, parse_species}, + }, + }; #[test] fn test_parse_polynomial_block() { @@ -191,6 +198,125 @@ mod test { assert_vec_delta!(real, polynomial.a, 1e-9); assert_delta!(polynomial.temp_range.0, 1000.000, 1e-3); - assert_delta!(polynomial.temp_range.1, 6000.0007, 1e-3); + assert_delta!(polynomial.temp_range.1, 6000.000, 1e-3); + } + + #[test] + fn test_parse_polynomials_block() { + let polynomials_block = r#" 300.000 1000.0007 -2.0 -1.0 0.0 1.0 2.0 3.0 4.0 0.0 6918.671 + 5.006608890D+03 1.861304407D+01 2.412531111D+00 1.987604647D-04-2.432362152D-07 + 1.538281506D-10-3.944375734D-14 3.887412680D+04 6.086585765D+00 + 1000.000 6000.0007 -2.0 -1.0 0.0 1.0 2.0 3.0 4.0 0.0 6918.671 +-2.920820938D+04 1.167751876D+02 2.356906505D+00 7.737231520D-05-1.529455262D-08 +-9.971670260D-13 5.053278264D-16 3.823288650D+04 6.600920155D+00 + 6000.000 20000.0007 -2.0 -1.0 0.0 1.0 2.0 3.0 4.0 0.0 6918.671 +-5.040682320D+08 3.802322650D+05-1.082347159D+02 1.549444292D-02-1.070103856D-06 + 3.592110900D-11-4.696039394D-16 -2.901050501D+06 9.491883160D+02"#; + + let mut lines = polynomials_block.lines(); + let polynomials = parse_polynomials_block(&mut lines, 3).unwrap(); + + let real_coeff_1 = [ + 5.006608890e+03, + 1.861304407e+01, + 2.412531111e+00, + 1.987604647e-04, + -2.432362152e-07, + 1.538281506e-10, + -3.944375734e-14, + 3.887412680e+04, + 6.086585765e+00, + ]; + + assert_vec_delta!(real_coeff_1, polynomials[0].a, 1e-9); + assert_delta!(polynomials[0].temp_range.0, 300.000, 1e-3); + assert_delta!(polynomials[0].temp_range.1, 1000.000, 1e-3); + + let real_coeff_2 = [ + -2.920820938e+04, + 1.167751876e+02, + 2.356906505e+00, + 7.737231520e-05, + -1.529455262e-08, + -9.971670260e-13, + 5.053278264e-16, + 3.823288650e+04, + 6.600920155e+00, + ]; + assert_vec_delta!(real_coeff_2, polynomials[1].a, 1e-9); + assert_delta!(polynomials[1].temp_range.0, 1000.000, 1e-3); + assert_delta!(polynomials[1].temp_range.1, 6000.000, 1e-3); + + let real_coeff_3 = [ + -5.040682320e+08, + 3.802322650e+05, + -1.082347159e+02, + 1.549444292e-02, + -1.070103856e-06, + 3.592110900e-11, + -4.696039394e-16, + -2.901050501e+06, + 9.491883160e+02, + ]; + assert_vec_delta!(real_coeff_3, polynomials[2].a, 1e-9); + assert_delta!(polynomials[2].temp_range.0, 6000.000, 1e-3); + assert_delta!(polynomials[2].temp_range.1, 20000.000, 1e-3); + } + + #[test] + fn test_parse_species() { + let species = r#"ALBr2 Gurvich,1996a pt1 p186 pt2 p149. + 2 tpis96 AL 1.00BR 2.00 0.00 0.00 0.00 0 186.7895380 -140662.125 + 300.000 1000.0007 -2.0 -1.0 0.0 1.0 2.0 3.0 4.0 0.0 13397.875 + 3.199375870D+04-7.119178970D+02 9.478258110D+00-4.875531670D-03 5.516512990D-06 +-3.340053040D-09 8.368476840D-13 -1.540591306D+04-1.742171366D+01 + 1000.000 6000.0007 -2.0 -1.0 0.0 1.0 2.0 3.0 4.0 0.0 13397.875 +-3.523782900D+05 4.671544170D+02 7.111908190D+00-5.551709200D-04 3.166301130D-07 +-5.521028330D-11 3.176725950D-15 -2.265004078D+04-2.695610360D+00"#; + + let mut lines = species.lines(); + let species = parse_species(&mut lines).unwrap(); + + assert_eq!(species.name, "ALBr2"); + assert_eq!(species.elements.len(), 2); + assert_eq!(species.elements[0].element, "AL"); + assert_eq!(species.elements[0].count, 1.0); + assert_eq!(species.elements[1].element, "BR"); + assert_eq!(species.elements[1].count, 2.0); + assert!(matches!(species.phase, Phase::Gas)); + assert_delta!(species.molecular_weight, 186.7895380, 1e-7); + assert_delta!(species.h_formation, -140662.125, 1e-3); + + let real_coeff_1 = [ + 3.199375870e+04, + -7.119178970e+02, + 9.478258110e+00, + -4.875531670e-03, + 5.516512990e-06, + -3.340053040e-09, + 8.368476840e-13, + -1.540591306e+04, + -1.742171366e+01, + ]; + + assert_vec_delta!(species.polynomials[0].a, real_coeff_1, 1e-9); + assert_delta!(species.polynomials[0].temp_range.0, 300.000, 1e-3); + assert_delta!(species.polynomials[0].temp_range.1, 1000.000, 1e-3); + + let real_coeff_2 = [ + -3.523782900e+05, + 4.671544170e+02, + 7.111908190e+00, + -5.551709200e-04, + 3.166301130e-07, + -5.521028330e-11, + 3.176725950e-15, + -2.265004078e+04, + -2.695610360e+00, + ]; + + assert_vec_delta!(species.polynomials[1].a, real_coeff_2, 1e-9); + assert_delta!(species.polynomials[1].temp_range.0, 1000.000, 1e-3); + assert_delta!(species.polynomials[1].temp_range.1, 6000.000, 1e-3); } }