mirror of
https://github.com/aselimov/cea-rs.git
synced 2026-04-19 00:24:20 +00:00
Reorganize some code and add the start of the transport file parsing
This commit is contained in:
parent
d5ed4c7599
commit
3548d8b449
7 changed files with 281 additions and 28 deletions
|
|
@ -1,6 +1,9 @@
|
|||
mod data;
|
||||
mod thermo_db;
|
||||
mod error;
|
||||
mod polynomials;
|
||||
mod thermo_db;
|
||||
mod thermo_fit;
|
||||
mod transport_db;
|
||||
mod transport_fit;
|
||||
mod utils;
|
||||
|
||||
pub use error::PropertiesError;
|
||||
|
|
|
|||
29
src/properties/test_thermo.inp
Normal file
29
src/properties/test_thermo.inp
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
thermo
|
||||
200.00 1000.00 6000.00 20000. 1/1/2024
|
||||
! Simple test thermo file with H2, O2, and H2O
|
||||
H2 Hydrogen gas
|
||||
2 test H 2.00 0.00 0.00 0.00 0.00 0 2.01588000 0.000
|
||||
200.000 1000.0007 -2.0 -1.0 0.0 1.0 2.0 3.0 4.0 0.0 8468.102
|
||||
4.078323210D+04-8.009186040D+02 8.214701670D+00-1.269714457D-02 1.753605076D-05
|
||||
-1.202860270D-08 3.368093490D-12 2.682484665D+03-3.043788844D+01
|
||||
1000.000 6000.0007 -2.0 -1.0 0.0 1.0 2.0 3.0 4.0 0.0 8468.102
|
||||
5.608128010D+05-8.371504740D+02 2.975364532D+00 1.252249124D-03-3.740716190D-07
|
||||
5.936625200D-11-3.606994100D-15 5.339824410D+03-2.202774769D+00
|
||||
O2 Oxygen gas
|
||||
2 test O 2.00 0.00 0.00 0.00 0.00 0 31.99880000 0.000
|
||||
200.000 1000.0007 -2.0 -1.0 0.0 1.0 2.0 3.0 4.0 0.0 8680.104
|
||||
-3.425563420D+04 4.847000970D+02 1.119010961D+00 4.293889240D-03-6.836300520D-07
|
||||
-2.023372700D-09 1.039040018D-12 -3.391454870D+03 1.849699470D+01
|
||||
1000.000 6000.0007 -2.0 -1.0 0.0 1.0 2.0 3.0 4.0 0.0 8680.104
|
||||
-1.037939022D+06 2.344830282D+03 1.819732036D+00 1.267847582D-03-2.188067988D-07
|
||||
2.053719572D-11-8.193467050D-16 -1.689010929D+04 1.738716506D+01
|
||||
H2O Water vapor
|
||||
2 test H 2.00 O 1.00 0.00 0.00 0.00 0 18.01528000 -241826.000
|
||||
200.000 1000.0007 -2.0 -1.0 0.0 1.0 2.0 3.0 4.0 0.0 9904.092
|
||||
-3.947960830D+04 5.755731020D+02 9.317826530D-01 7.222712860D-03-7.342557370D-06
|
||||
4.955043490D-09-1.336933246D-12 -3.303974310D+04 1.724205775D+01
|
||||
1000.000 6000.0007 -2.0 -1.0 0.0 1.0 2.0 3.0 4.0 0.0 9904.092
|
||||
1.034972096D+06-2.412698562D+03 4.646110780D+00 2.291998307D-03-6.836830480D-07
|
||||
9.426468930D-11-4.822380530D-15 -1.384286509D+04-7.978148510D+00
|
||||
END PRODUCTS
|
||||
END REACTANTS
|
||||
|
|
@ -1,27 +1,14 @@
|
|||
use crate::properties::{
|
||||
PropertiesError,
|
||||
error::make_parse_error,
|
||||
polynomials::{Phase, Polynomial, SpeciesElement, SpeciesPolynomial},
|
||||
thermo_fit::{Phase, SpeciesElement, SpeciesThermoData, ThermoPolynomial},
|
||||
utils::parse_fields,
|
||||
};
|
||||
|
||||
fn parse_fields(line: &str, widths: &[usize]) -> Vec<String> {
|
||||
let mut fields = Vec::new();
|
||||
let mut pos = 0;
|
||||
|
||||
for &width in widths {
|
||||
if let Some(field) = line.get(pos..pos + width) {
|
||||
// The replace chnages the fortran formatted D exponential for the normal E exponential
|
||||
fields.push(field.trim().replace("D", "E"));
|
||||
}
|
||||
pos += width;
|
||||
}
|
||||
|
||||
fields
|
||||
}
|
||||
|
||||
pub struct ThermoDB {
|
||||
pub products: Vec<SpeciesPolynomial>,
|
||||
pub reactants: Vec<SpeciesPolynomial>,
|
||||
pub products: Vec<SpeciesThermoData>,
|
||||
pub reactants: Vec<SpeciesThermoData>,
|
||||
}
|
||||
|
||||
/// Parse a thermo formatted db
|
||||
|
|
@ -59,7 +46,7 @@ impl ThermoDB {
|
|||
fn parse_species<'a>(
|
||||
line: &str,
|
||||
lines: &mut impl Iterator<Item = &'a str>,
|
||||
) -> Result<SpeciesPolynomial, PropertiesError> {
|
||||
) -> Result<SpeciesThermoData, PropertiesError> {
|
||||
// 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];
|
||||
|
|
@ -112,7 +99,7 @@ fn parse_species<'a>(
|
|||
lines.next().ok_or(PropertiesError::InvalidFile)?;
|
||||
}
|
||||
|
||||
Ok(SpeciesPolynomial {
|
||||
Ok(SpeciesThermoData {
|
||||
name,
|
||||
polynomials,
|
||||
elements,
|
||||
|
|
@ -125,7 +112,7 @@ fn parse_species<'a>(
|
|||
fn parse_polynomials_block<'a>(
|
||||
lines: &mut impl Iterator<Item = &'a str>,
|
||||
intervals: usize,
|
||||
) -> Result<Vec<Polynomial>, PropertiesError> {
|
||||
) -> Result<Vec<ThermoPolynomial>, PropertiesError> {
|
||||
// Now parse the actual polynomial intervals
|
||||
(0..intervals)
|
||||
.map(|_| parse_polynomial_block(lines))
|
||||
|
|
@ -134,7 +121,7 @@ fn parse_polynomials_block<'a>(
|
|||
|
||||
fn parse_polynomial_block<'a>(
|
||||
lines: &mut impl Iterator<Item = &'a str>,
|
||||
) -> Result<Polynomial, PropertiesError> {
|
||||
) -> Result<ThermoPolynomial, PropertiesError> {
|
||||
// Ignore the coefficients since they are the same
|
||||
const SPECIES_INTERVAL_1_WIDTHS: &[usize] = &[11, 11];
|
||||
const SPECIES_INTERVAL_2_WIDTHS: &[usize] = &[16; 5];
|
||||
|
|
@ -169,7 +156,7 @@ fn parse_polynomial_block<'a>(
|
|||
);
|
||||
}
|
||||
|
||||
Ok(Polynomial {
|
||||
Ok(ThermoPolynomial {
|
||||
a,
|
||||
temp_range: (temp_lo, temp_hi),
|
||||
})
|
||||
|
|
@ -180,8 +167,8 @@ mod test {
|
|||
use crate::{
|
||||
assert_delta, assert_vec_delta,
|
||||
properties::{
|
||||
polynomials::Phase,
|
||||
thermo_db::{ThermoDB, parse_polynomial_block, parse_polynomials_block, parse_species},
|
||||
thermo_fit::Phase,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,15 +3,15 @@ pub enum Phase {
|
|||
Condensed,
|
||||
}
|
||||
|
||||
pub struct SpeciesPolynomial {
|
||||
pub struct SpeciesThermoData {
|
||||
pub name: String,
|
||||
pub elements: Vec<SpeciesElement>,
|
||||
pub phase: Phase,
|
||||
pub polynomials: Vec<Polynomial>,
|
||||
pub polynomials: Vec<ThermoPolynomial>,
|
||||
pub molecular_weight: f64,
|
||||
pub h_formation: f64,
|
||||
}
|
||||
pub struct Polynomial {
|
||||
pub struct ThermoPolynomial {
|
||||
pub a: Vec<f64>,
|
||||
pub temp_range: (f64, f64),
|
||||
}
|
||||
207
src/properties/transport_db.rs
Normal file
207
src/properties/transport_db.rs
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
use crate::properties::{
|
||||
PropertiesError,
|
||||
error::make_parse_error,
|
||||
transport_fit::{SpeciesTransportData, TransportFit},
|
||||
utils::parse_fields,
|
||||
};
|
||||
|
||||
enum ViscosityOrConductivity {
|
||||
Viscosity,
|
||||
Conductivity,
|
||||
}
|
||||
|
||||
pub struct TransportDB {
|
||||
data: Vec<SpeciesTransportData>,
|
||||
}
|
||||
|
||||
impl TransportDB {
|
||||
pub fn parse() {}
|
||||
}
|
||||
|
||||
fn parse_species_transport_block<'a>(
|
||||
mut lines: impl Iterator<Item = &'a str>,
|
||||
) -> Result<SpeciesTransportData, PropertiesError> {
|
||||
let line = lines.next().ok_or(PropertiesError::InvalidFile)?;
|
||||
let mut viscosities = vec![];
|
||||
let mut conductivities = vec![];
|
||||
let (name, viscosity_count, conductivity_count) = parse_species_header_line(line)?;
|
||||
for _ in 0..viscosity_count + conductivity_count {
|
||||
let line = lines.next().ok_or(PropertiesError::InvalidFile)?;
|
||||
match parse_coefficients(line)? {
|
||||
(ViscosityOrConductivity::Viscosity, fit) => viscosities.push(fit),
|
||||
(ViscosityOrConductivity::Conductivity, fit) => conductivities.push(fit),
|
||||
}
|
||||
}
|
||||
Ok(SpeciesTransportData {
|
||||
name,
|
||||
viscosities,
|
||||
conductivities,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_species_header_line(line: &str) -> Result<(String, usize, usize), PropertiesError> {
|
||||
const HEADER_WIDTHS: &[usize] = &[34, 1, 1, 1, 1];
|
||||
|
||||
let splits = parse_fields(line, HEADER_WIDTHS);
|
||||
|
||||
let name = splits[0].to_string();
|
||||
let viscosity_count: usize = splits[2]
|
||||
.parse()
|
||||
.map_err(|_| make_parse_error("V", "usize", &splits[2]))?;
|
||||
|
||||
let conductivity_count: usize = splits[4]
|
||||
.parse()
|
||||
.map_err(|_| make_parse_error("C", "usize", &splits[2]))?;
|
||||
Ok((name, viscosity_count, conductivity_count))
|
||||
}
|
||||
|
||||
fn parse_coefficients(
|
||||
line: &str,
|
||||
) -> Result<(ViscosityOrConductivity, TransportFit), PropertiesError> {
|
||||
const COEFFICIENTS_WIDTH: &[usize] = &[2, 7, 11, 15, 15, 15, 15];
|
||||
let splits = parse_fields(line, COEFFICIENTS_WIDTH);
|
||||
let transport_type = if splits[0].contains("V") {
|
||||
ViscosityOrConductivity::Viscosity
|
||||
} else {
|
||||
ViscosityOrConductivity::Conductivity
|
||||
};
|
||||
Ok((
|
||||
transport_type,
|
||||
TransportFit {
|
||||
temp_range: (
|
||||
splits[1]
|
||||
.parse()
|
||||
.map_err(|_| make_parse_error("tlo", "f64", &splits[1]))?,
|
||||
splits[2]
|
||||
.parse()
|
||||
.map_err(|_| make_parse_error("tlo", "f64", &splits[2]))?,
|
||||
),
|
||||
a: splits[3]
|
||||
.parse()
|
||||
.map_err(|_| make_parse_error("a", "f64", &splits[3]))?,
|
||||
b: splits[4]
|
||||
.parse()
|
||||
.map_err(|_| make_parse_error("a", "f64", &splits[4]))?,
|
||||
c: splits[5]
|
||||
.parse()
|
||||
.map_err(|_| make_parse_error("a", "f64", &splits[5]))?,
|
||||
|
||||
d: splits[6]
|
||||
.parse()
|
||||
.map_err(|_| make_parse_error("a", "f64", &splits[6]))?,
|
||||
},
|
||||
))
|
||||
}
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use crate::{
|
||||
assert_delta,
|
||||
properties::transport_db::{
|
||||
ViscosityOrConductivity, parse_coefficients, parse_species_header_line,
|
||||
parse_species_transport_block,
|
||||
},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_parse_species_transport_header() {
|
||||
let line = "Ar V3C1 BICH ET AL (1990)";
|
||||
|
||||
let (name, viscosity_count, conductivity_count) = parse_species_header_line(line).unwrap();
|
||||
|
||||
assert_eq!(name, "Ar");
|
||||
assert_eq!(viscosity_count, 3);
|
||||
assert_eq!(conductivity_count, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_coefficients() {
|
||||
let line =
|
||||
" V 200.0 1000.0 0.61205763E 00-0.67714354E 02 0.19040660E 03 0.21588272E 01";
|
||||
let (transport_type, fit) = parse_coefficients(line).unwrap();
|
||||
|
||||
assert!(matches!(transport_type, ViscosityOrConductivity::Viscosity));
|
||||
assert_delta!(fit.temp_range.0, 200.0, 1e-1);
|
||||
assert_delta!(fit.temp_range.1, 1000.0, 1e-1);
|
||||
assert_delta!(fit.a, 0.61205763e00, 1e-8);
|
||||
assert_delta!(fit.b, -0.67714354E02, 1e-8);
|
||||
assert_delta!(fit.c, 0.19040660e03, 1e-8);
|
||||
assert_delta!(fit.d, 0.21588272E01, 1e-8);
|
||||
|
||||
let line =
|
||||
" C 5000.0 15000.0 0.76269502E+00 0.62341752E+03-0.71899552E+06 0.56927918E+00";
|
||||
|
||||
let (transport_type, fit) = parse_coefficients(line).unwrap();
|
||||
assert!(matches!(
|
||||
transport_type,
|
||||
ViscosityOrConductivity::Conductivity
|
||||
));
|
||||
assert_delta!(fit.temp_range.0, 5000.0, 1e-1);
|
||||
assert_delta!(fit.temp_range.1, 15000.0, 1e-1);
|
||||
assert_delta!(fit.a, 0.76269502E+00, 1e-8);
|
||||
assert_delta!(fit.b, 0.62341752E+03, 1e-8);
|
||||
assert_delta!(fit.c, -0.71899552E+06, 1e-8);
|
||||
assert_delta!(fit.d, 0.56927918E+00, 1e-8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_transport_species_block() {
|
||||
let species_block = r#"Ar V3C3 BICH ET AL (1990)
|
||||
V 200.0 1000.0 0.61205763E 00-0.67714354E 02 0.19040660E 03 0.21588272E 01
|
||||
V 1000.0 5000.0 0.69357334E 00 0.70953943E 02-0.28386007E 05 0.14856447E 01
|
||||
V 5000.0 15000.0 0.76608935E+00 0.67867215E+03-0.84991417E+06 0.77935167E+00
|
||||
C 200.0 1000.0 0.60968928E 00-0.70892249E 02 0.58420624E 03 0.19337152E 01
|
||||
C 1000.0 5000.0 0.69075463E 00 0.62676058E 02-0.25667413E 05 0.12664189E 01
|
||||
C 5000.0 15000.0 0.76269502E+00 0.62341752E+03-0.71899552E+06 0.56927918E+00"#;
|
||||
|
||||
let lines = species_block.lines();
|
||||
let species_data = parse_species_transport_block(lines).unwrap();
|
||||
|
||||
assert_eq!(species_data.name, "Ar");
|
||||
assert_eq!(species_data.viscosities.len(), 3);
|
||||
assert_eq!(species_data.conductivities.len(), 3);
|
||||
|
||||
// Viscosity fits
|
||||
assert_delta!(species_data.viscosities[0].temp_range.0, 200.0, 1e-1);
|
||||
assert_delta!(species_data.viscosities[0].temp_range.1, 1000.0, 1e-1);
|
||||
assert_delta!(species_data.viscosities[0].a, 0.61205763e00, 1e-8);
|
||||
assert_delta!(species_data.viscosities[0].b, -0.67714354e02, 1e-8);
|
||||
assert_delta!(species_data.viscosities[0].c, 0.19040660e03, 1e-8);
|
||||
assert_delta!(species_data.viscosities[0].d, 0.21588272e01, 1e-8);
|
||||
|
||||
assert_delta!(species_data.viscosities[1].temp_range.0, 1000.0, 1e-1);
|
||||
assert_delta!(species_data.viscosities[1].temp_range.1, 5000.0, 1e-1);
|
||||
assert_delta!(species_data.viscosities[1].a, 0.69357334e00, 1e-8);
|
||||
assert_delta!(species_data.viscosities[1].b, 0.70953943e02, 1e-8);
|
||||
assert_delta!(species_data.viscosities[1].c, -0.28386007e05, 1e-8);
|
||||
assert_delta!(species_data.viscosities[1].d, 0.14856447e01, 1e-8);
|
||||
|
||||
assert_delta!(species_data.viscosities[2].temp_range.0, 5000.0, 1e-1);
|
||||
assert_delta!(species_data.viscosities[2].temp_range.1, 15000.0, 1e-1);
|
||||
assert_delta!(species_data.viscosities[2].a, 0.76608935e00, 1e-8);
|
||||
assert_delta!(species_data.viscosities[2].b, 0.67867215e03, 1e-8);
|
||||
assert_delta!(species_data.viscosities[2].c, -0.84991417e06, 1e-8);
|
||||
assert_delta!(species_data.viscosities[2].d, 0.77935167e00, 1e-8);
|
||||
|
||||
// Conductivity fits
|
||||
assert_delta!(species_data.conductivities[0].temp_range.0, 200.0, 1e-1);
|
||||
assert_delta!(species_data.conductivities[0].temp_range.1, 1000.0, 1e-1);
|
||||
assert_delta!(species_data.conductivities[0].a, 0.60968928e00, 1e-8);
|
||||
assert_delta!(species_data.conductivities[0].b, -0.70892249e02, 1e-8);
|
||||
assert_delta!(species_data.conductivities[0].c, 0.58420624e03, 1e-8);
|
||||
assert_delta!(species_data.conductivities[0].d, 0.19337152e01, 1e-8);
|
||||
|
||||
assert_delta!(species_data.conductivities[1].temp_range.0, 1000.0, 1e-1);
|
||||
assert_delta!(species_data.conductivities[1].temp_range.1, 5000.0, 1e-1);
|
||||
assert_delta!(species_data.conductivities[1].a, 0.69075463e00, 1e-8);
|
||||
assert_delta!(species_data.conductivities[1].b, 0.62676058e02, 1e-8);
|
||||
assert_delta!(species_data.conductivities[1].c, -0.25667413e05, 1e-8);
|
||||
assert_delta!(species_data.conductivities[1].d, 0.12664189e01, 1e-8);
|
||||
|
||||
assert_delta!(species_data.conductivities[2].temp_range.0, 5000.0, 1e-1);
|
||||
assert_delta!(species_data.conductivities[2].temp_range.1, 15000.0, 1e-1);
|
||||
assert_delta!(species_data.conductivities[2].a, 0.76269502e00, 1e-8);
|
||||
assert_delta!(species_data.conductivities[2].b, 0.62341752e03, 1e-8);
|
||||
assert_delta!(species_data.conductivities[2].c, -0.71899552e06, 1e-8);
|
||||
assert_delta!(species_data.conductivities[2].d, 0.56927918e00, 1e-8);
|
||||
}
|
||||
}
|
||||
13
src/properties/transport_fit.rs
Normal file
13
src/properties/transport_fit.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
pub struct SpeciesTransportData {
|
||||
pub name: String,
|
||||
pub viscosities: Vec<TransportFit>,
|
||||
pub conductivities: Vec<TransportFit>,
|
||||
}
|
||||
|
||||
pub struct TransportFit {
|
||||
pub temp_range: (f64, f64),
|
||||
pub a: f64,
|
||||
pub b: f64,
|
||||
pub c: f64,
|
||||
pub d: f64,
|
||||
}
|
||||
14
src/properties/utils.rs
Normal file
14
src/properties/utils.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
pub fn parse_fields(line: &str, widths: &[usize]) -> Vec<String> {
|
||||
let mut fields = Vec::new();
|
||||
let mut pos = 0;
|
||||
|
||||
for &width in widths {
|
||||
if let Some(field) = line.get(pos..pos + width) {
|
||||
// The replace changes the fortran formatted D exponential for the normal E exponential
|
||||
fields.push(field.trim().replace("D", "E").replace("E ", "E"));
|
||||
}
|
||||
pos += width;
|
||||
}
|
||||
|
||||
fields
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue