Skip to content

Commit

Permalink
Merge branch 'f3/thermal' of github.com:NREL/fastsim into f3/thermal
Browse files Browse the repository at this point in the history
  • Loading branch information
calbaker committed Jan 27, 2025
2 parents 376a39a + fe013e8 commit 755f088
Show file tree
Hide file tree
Showing 13 changed files with 252 additions and 217 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions cal_and_val/thermal/f3-vehicles/2020 Chevrolet Bolt EV.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ year: 2020
cabin:
LumpedCabin:
# 0.05 is Chad's uncalibrated estimate
cab_shell_htc_to_amb_watts_per_square_meter_degree_celsius: 0.05
cab_shell_htc_to_amb_watts_per_square_meter_kelvin: 0.05
# 0.05 is Chad's uncalibrated estimate
cab_htc_to_amb_stop_watts_per_square_meter_degree_celsius: 0.05
cab_htc_to_amb_stop_watts_per_square_meter_kelvin: 0.05
# 200,000 is Chad's uncalibrated estimate
heat_capacitance_joules_per_kelvin: 200000
# TODO: get actual vehicle length, but calibrate this later
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pt_type:
FuelConverterThermal:
heat_capacitance_joules_per_kelvin: 200000.0
length_for_convection_meters: 1.0
htc_to_amb_stop_watts_per_square_meter_degree_celsius: 50.0
htc_to_amb_stop_watts_per_square_meter_kelvin: 50.0
conductance_from_comb_watts_per_kelvin: 5.0
max_frac_from_comb: 0.5
tstat_te_sto_kelvin: 358.15
Expand Down Expand Up @@ -226,8 +226,8 @@ chassis:
cargo_mass_kilograms: ~
cabin:
LumpedCabin:
cab_shell_htc_to_amb_watts_per_square_meter_degree_celsius: 0.05
cab_htc_to_amb_stop_watts_per_square_meter_degree_celsius: 0.05
cab_shell_htc_to_amb_watts_per_square_meter_kelvin: 0.05
cab_htc_to_amb_stop_watts_per_square_meter_kelvin: 0.05
heat_capacitance_joules_per_kelvin: 200000.0
length_meters: 2.5
width_meters: 2.0
Expand All @@ -253,32 +253,3 @@ mass_kilograms: 1508.195
pwr_aux_base_watts: 500.0
trans_eff: 0.98
save_interval: 1
state:
i: 0
pwr_prop_fwd_max_watts: 0.0
pwr_prop_bwd_max_watts: 0.0
pwr_tractive_watts: 0.0
pwr_tractive_for_cyc_watts: 0.0
energy_tractive_joules: 0.0
pwr_aux_watts: 0.0
energy_aux_joules: 0.0
pwr_drag_watts: 0.0
energy_drag_joules: 0.0
pwr_accel_watts: 0.0
energy_accel_joules: 0.0
pwr_ascent_watts: 0.0
energy_ascent_joules: 0.0
pwr_rr_watts: 0.0
energy_rr_joules: 0.0
pwr_whl_inertia_watts: 0.0
energy_whl_inertia_joules: 0.0
pwr_brake_watts: 0.0
energy_brake_joules: 0.0
cyc_met: true
cyc_met_overall: true
speed_ach_meters_per_second: 0.0
dist_meters: 0.0
grade_curr: 0.0
elev_curr_meters: .nan
air_density_kilograms_per_cubic_meter: 1.172
mass_kilograms: .nan
2 changes: 1 addition & 1 deletion fastsim-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ toml = { version = "0.8.12", optional = true }
derive_more = { version = "1.0.0", features = ["from_str", "from", "is_variant", "try_into"] }
ureq = { version = "2.9.1", optional = true }
url = { version = "2.5.0", optional = true }
ninterp = { version = "0.2.0", features = ["serde"] }
ninterp = { version = "0.2.1", features = ["serde"] }

[dev-dependencies]
pretty_assertions = "1.4.1"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,16 +193,19 @@ pub(crate) fn impl_getters_and_setters(field: &mut syn::Field) -> Option<()> {
"Ratio" => extract_units!(uom::si::ratio::ratio),
"Time" => extract_units!(uom::si::time::second, uom::si::time::hour),
"HeatTransferCoeff" => extract_units!(
uom::si::heat_transfer::watt_per_square_meter_degree_celsius,
uom::si::heat_transfer::watt_per_square_meter_kelvin
uom::si::heat_transfer::watt_per_square_meter_kelvin,
uom::si::heat_transfer::watt_per_square_meter_degree_celsius
),
"HeatCapacity" => {
extract_units!(
uom::si::heat_capacity::joule_per_kelvin,
uom::si::heat_capacity::joule_per_degree_celsius
)
}
"Temperature" => extract_units!(uom::si::temperature_interval::kelvin),
"TemperatureInterval" => extract_units!(uom::si::temperature_interval::kelvin),
"Temperature" => {
extract_units!(uom::si::thermodynamic_temperature::kelvin)
}
"ThermalConductance" => {
extract_units!(uom::si::thermal_conductance::watt_per_kelvin)
}
Expand Down
74 changes: 37 additions & 37 deletions fastsim-core/src/gas_properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ lazy_static! {
#[pyo3(name = "get_therm_cond")]
#[staticmethod]
pub fn get_therm_cond_py(te_air: f64) -> anyhow::Result<f64> {
Ok(Self::get_therm_cond(te_air * uc::KELVIN - *uc::CELSIUS_TO_KELVIN)?.get::<si::watt_per_meter_kelvin>())
Ok(Self::get_therm_cond((te_air + uc::CELSIUS_TO_KELVIN) * uc::KELVIN)?.get::<si::watt_per_meter_kelvin>())
}
/// Returns constant pressure specific heat [J/(kg*K)] of air
Expand All @@ -54,7 +54,7 @@ lazy_static! {
#[pyo3(name = "get_specific_heat_cp")]
#[staticmethod]
pub fn get_specific_heat_cp_py(te_air: f64) -> anyhow::Result<f64> {
Ok(Self::get_specific_heat_cp(te_air * uc::KELVIN - *uc::CELSIUS_TO_KELVIN)?.get::<si::joule_per_kilogram_kelvin>())
Ok(Self::get_specific_heat_cp((te_air + uc::CELSIUS_TO_KELVIN) * uc::KELVIN)?.get::<si::joule_per_kilogram_kelvin>())
}
/// Returns specific enthalpy [J/kg] of air
Expand All @@ -63,7 +63,7 @@ lazy_static! {
#[pyo3(name = "get_specific_enthalpy")]
#[staticmethod]
pub fn get_specific_enthalpy_py(te_air: f64) -> anyhow::Result<f64> {
Ok(Self::get_specific_enthalpy(te_air * uc::KELVIN - *uc::CELSIUS_TO_KELVIN)?.get::<si::joule_per_kilogram>())
Ok(Self::get_specific_enthalpy((te_air - uc::CELSIUS_TO_KELVIN) * uc::KELVIN)?.get::<si::joule_per_kilogram>())
}
/// Returns specific energy [J/kg] of air
Expand All @@ -72,7 +72,7 @@ lazy_static! {
#[pyo3(name = "get_specific_energy")]
#[staticmethod]
pub fn get_specific_energy_py(te_air: f64) -> anyhow::Result<f64> {
Ok(Self::get_specific_energy(te_air * uc::KELVIN - *uc::CELSIUS_TO_KELVIN)?.get::<si::joule_per_kilogram>())
Ok(Self::get_specific_energy((te_air - uc::CELSIUS_TO_KELVIN) * uc::KELVIN)?.get::<si::joule_per_kilogram>())
}
/// Returns thermal Prandtl number of air
Expand All @@ -81,7 +81,7 @@ lazy_static! {
#[pyo3(name = "get_pr")]
#[staticmethod]
pub fn get_pr_py(te_air: f64) -> anyhow::Result<f64> {
Ok(Self::get_pr(te_air * uc::KELVIN - *uc::CELSIUS_TO_KELVIN)?.get::<si::ratio>())
Ok(Self::get_pr((te_air - uc::CELSIUS_TO_KELVIN) * uc::KELVIN )?.get::<si::ratio>())
}
/// Returns dynamic viscosity \[Pa*s\] of air
Expand All @@ -90,7 +90,7 @@ lazy_static! {
#[pyo3(name = "get_dyn_visc")]
#[staticmethod]
pub fn get_dyn_visc_py(te_air: f64) -> anyhow::Result<f64> {
Ok(Self::get_dyn_visc(te_air * uc::KELVIN - *uc::CELSIUS_TO_KELVIN)?.get::<si::pascal_second>())
Ok(Self::get_dyn_visc((te_air - uc::CELSIUS_TO_KELVIN) * uc::KELVIN)?.get::<si::pascal_second>())
}
/// Returns temperature [°C] of air
Expand All @@ -99,7 +99,7 @@ lazy_static! {
#[pyo3(name = "get_te_from_h")]
#[staticmethod]
pub fn get_te_from_h_py(h: f64) -> anyhow::Result<f64> {
Ok(Self::get_te_from_h(h * uc::J_PER_KG)?.get::<si::kelvin>() - uc::CELSIUS_TO_KELVIN.value)
Ok(Self::get_te_from_h(h * uc::J_PER_KG)?.get::<si::degree_celsius>())
}
/// Returns temperature [°C] of air
Expand All @@ -108,7 +108,7 @@ lazy_static! {
#[pyo3(name = "get_te_from_u")]
#[staticmethod]
pub fn get_te_from_u_py(u: f64) -> anyhow::Result<f64> {
Ok(Self::get_te_from_u(u * uc::J_PER_KG)?.get::<si::kelvin>() - uc::CELSIUS_TO_KELVIN.value)
Ok(Self::get_te_from_u(u * uc::J_PER_KG)?.get::<si::degree_celsius>())
}
)]
Expand Down Expand Up @@ -151,7 +151,7 @@ impl Air {
/// - `te_air`: temperature of air
pub fn get_therm_cond(te_air: si::Temperature) -> anyhow::Result<si::ThermalConductivity> {
Ok(
asp::THERMAL_CONDUCTIVITY_INTERP.interpolate(&[te_air.get::<si::kelvin>()])?
asp::THERMAL_CONDUCTIVITY_INTERP.interpolate(&[te_air.get::<si::degree_celsius>()])?
* uc::WATT_PER_METER_KELVIN,
)
}
Expand All @@ -162,35 +162,38 @@ impl Air {
pub fn get_specific_heat_cp(
te_air: si::Temperature,
) -> anyhow::Result<si::SpecificHeatCapacity> {
Ok(asp::C_P_INTERP.interpolate(&[te_air.get::<si::kelvin>()])? * uc::J_PER_KG_K)
Ok(asp::C_P_INTERP.interpolate(&[te_air.get::<si::degree_celsius>()])? * uc::J_PER_KG_K)
}

/// Returns specific enthalpy of air
/// # Arguments
/// - `te_air`: temperature of air
pub fn get_specific_enthalpy(te_air: si::Temperature) -> anyhow::Result<si::SpecificEnergy> {
Ok(asp::ENTHALPY_INTERP.interpolate(&[te_air.get::<si::kelvin>()])? * uc::J_PER_KG)
Ok(asp::ENTHALPY_INTERP.interpolate(&[te_air.get::<si::degree_celsius>()])? * uc::J_PER_KG)
}

/// Returns specific energy of air
/// # Arguments
/// - `te_air`: temperature of air
pub fn get_specific_energy(te_air: si::Temperature) -> anyhow::Result<si::SpecificEnergy> {
Ok(asp::ENERGY_INTERP.interpolate(&[te_air.get::<si::kelvin>()])? * uc::J_PER_KG)
Ok(asp::ENERGY_INTERP.interpolate(&[te_air.get::<si::degree_celsius>()])? * uc::J_PER_KG)
}

/// Returns thermal Prandtl number of air
/// # Arguments
/// - `te_air`: temperature of air
pub fn get_pr(te_air: si::Temperature) -> anyhow::Result<si::Ratio> {
Ok(asp::PRANDTL_INTERP.interpolate(&[te_air.get::<si::kelvin>()])? * uc::R)
Ok(asp::PRANDTL_INTERP.interpolate(&[te_air.get::<si::degree_celsius>()])? * uc::R)
}

/// Returns dynamic viscosity \[Pa*s\] of air
/// # Arguments
/// te_air: temperature of air
pub fn get_dyn_visc(te_air: si::Temperature) -> anyhow::Result<si::DynamicViscosity> {
Ok(asp::DYN_VISC_INTERP.interpolate(&[te_air.get::<si::kelvin>()])? * uc::PASCAL_SECOND)
Ok(
asp::DYN_VISC_INTERP.interpolate(&[te_air.get::<si::degree_celsius>()])?
* uc::PASCAL_SECOND,
)
}

/// Returns temperature of air
Expand Down Expand Up @@ -247,7 +250,7 @@ mod air_static_props {
use super::*;
lazy_static! {
/// Array of temperatures at which properties are evaluated
static ref TEMPERATURE_VALUES: Vec<si::Temperature> = [
static ref TEMPERATURE_DEG_C_VALUES: Vec<f64> = vec![
-60.,
-57.03690616,
-53.1958198,
Expand All @@ -273,19 +276,16 @@ mod air_static_props {
2947.10642291,
3841.10336915,
5000.
]
.iter()
.map(|x| *x * uc::KELVIN + *uc::CELSIUS_TO_KELVIN)
.collect();
];
pub static ref TEMP_FROM_ENTHALPY: Interpolator = Interpolator::new_1d(
ENTHALPY_VALUES.iter().map(|x| x.get::<si::joule_per_kilogram>()).collect::<Vec<f64>>(),
TEMPERATURE_VALUES.iter().map(|x| x.get::<si::kelvin>()).collect::<Vec<f64>>(),
TEMPERATURE_DEG_C_VALUES.clone(),
Strategy::Linear,
Extrapolate::Error
).unwrap();
pub static ref TEMP_FROM_ENERGY: Interpolator = Interpolator::new_1d(
ENERGY_VALUES.iter().map(|x| x.get::<si::joule_per_kilogram>()).collect::<Vec<f64>>(),
TEMPERATURE_VALUES.iter().map(|x| x.get::<si::kelvin>()).collect::<Vec<f64>>(),
TEMPERATURE_DEG_C_VALUES.clone(),
Strategy::Linear,
Extrapolate::Error
).unwrap();
Expand Down Expand Up @@ -321,7 +321,7 @@ mod air_static_props {
.map(|x| *x * uc::WATT_PER_METER_KELVIN)
.collect();
pub static ref THERMAL_CONDUCTIVITY_INTERP: Interpolator = Interpolator::new_1d(
TEMPERATURE_VALUES.iter().map(|x| x.get::<si::kelvin>()).collect::<Vec<f64>>(),
TEMPERATURE_DEG_C_VALUES.clone(),
THERMAL_CONDUCTIVITY_VALUES.iter().map(|x| x.get::<si::watt_per_meter_degree_celsius>()).collect::<Vec<f64>>(),
Strategy::Linear,
Extrapolate::Error
Expand Down Expand Up @@ -358,7 +358,7 @@ mod air_static_props {
.map(|x| *x * uc::J_PER_KG_K)
.collect();
pub static ref C_P_INTERP: Interpolator = Interpolator::new_1d(
TEMPERATURE_VALUES.iter().map(|x| x.get::<si::kelvin>()).collect::<Vec<f64>>(),
TEMPERATURE_DEG_C_VALUES.clone(),
C_P_VALUES.iter().map(|x| x.get::<si::joule_per_kilogram_kelvin>()).collect::<Vec<f64>>(),
Strategy::Linear,
Extrapolate::Error
Expand Down Expand Up @@ -394,7 +394,7 @@ mod air_static_props {
.map(|x| *x * uc::J_PER_KG)
.collect();
pub static ref ENTHALPY_INTERP: Interpolator = Interpolator::new_1d(
TEMPERATURE_VALUES.iter().map(|x| x.get::<si::kelvin>()).collect::<Vec<f64>>(),
TEMPERATURE_DEG_C_VALUES.clone(),
ENTHALPY_VALUES.iter().map(|x| x.get::<si::joule_per_kilogram>()).collect::<Vec<f64>>(),
Strategy::Linear,
Extrapolate::Error
Expand Down Expand Up @@ -430,7 +430,7 @@ mod air_static_props {
.map(|x| *x * uc::J_PER_KG)
.collect();
pub static ref ENERGY_INTERP: Interpolator = Interpolator::new_1d(
TEMPERATURE_VALUES.iter().map(|x| x.get::<si::kelvin>()).collect::<Vec<f64>>(),
TEMPERATURE_DEG_C_VALUES.clone(),
ENERGY_VALUES.iter().map(|x| x.get::<si::joule_per_kilogram>()).collect::<Vec<f64>>(),
Strategy::Linear,
Extrapolate::Error
Expand Down Expand Up @@ -466,7 +466,7 @@ mod air_static_props {
.map(|x| *x * uc::PASCAL_SECOND)
.collect();
pub static ref DYN_VISC_INTERP: Interpolator = Interpolator::new_1d(
TEMPERATURE_VALUES.iter().map(|x| x.get::<si::kelvin>()).collect::<Vec<f64>>(),
TEMPERATURE_DEG_C_VALUES.clone(),
DYN_VISCOSITY_VALUES.iter().map(|x| x.get::<si::pascal_second>()).collect::<Vec<f64>>(),
Strategy::Linear,
Extrapolate::Error
Expand All @@ -478,7 +478,7 @@ mod air_static_props {
.map(|((mu, c_p), k)| -> si::Ratio {*mu * *c_p / *k})
.collect::<Vec<si::Ratio>>();
pub static ref PRANDTL_INTERP: Interpolator = Interpolator::new_1d(
TEMPERATURE_VALUES.iter().map(|x| x.get::<si::kelvin>()).collect::<Vec<f64>>(),
TEMPERATURE_DEG_C_VALUES.clone(),
PRANDTL_VALUES.iter().map(|x| x.get::<si::ratio>()).collect::<Vec<f64>>(),
Strategy::Linear,
Extrapolate::Error
Expand Down Expand Up @@ -525,7 +525,7 @@ mod octane_static_props {
use super::*;
lazy_static! {
/// Array of temperatures at which properties are evaluated
static ref TEMPERATURE_VALUES: Vec<si::Temperature> = [
static ref TEMPERATURE_DEG_C_VALUES: Vec<f64> = vec![
-4.00000000e+01,
-3.70369062e+01,
-3.31958198e+01,
Expand All @@ -551,13 +551,10 @@ mod octane_static_props {
2.96710642e+03,
3.86110337e+03,
5.02000000e+03
]
.iter()
.map(|x| *x * uc::KELVIN + *uc::CELSIUS_TO_KELVIN)
.collect();
];
pub static ref TEMP_FROM_ENERGY: Interpolator = Interpolator::new_1d(
ENERGY_VALUES.iter().map(|x| x.get::<si::joule_per_kilogram>()).collect::<Vec<f64>>(),
TEMPERATURE_VALUES.iter().map(|x| x.get::<si::kelvin>()).collect::<Vec<f64>>(),
TEMPERATURE_DEG_C_VALUES.clone(),
Strategy::Linear,
Extrapolate::Error
).unwrap();
Expand Down Expand Up @@ -592,7 +589,7 @@ mod octane_static_props {
.map(|x| *x * uc::J_PER_KG)
.collect();
pub static ref ENERGY_INTERP: Interpolator = Interpolator::new_1d(
TEMPERATURE_VALUES.iter().map(|x| x.get::<si::kelvin>()).collect::<Vec<f64>>(),
TEMPERATURE_DEG_C_VALUES.clone(),
ENERGY_VALUES.iter().map(|x| x.get::<si::joule_per_kilogram>()).collect::<Vec<f64>>(),
Strategy::Linear,
Extrapolate::Error
Expand All @@ -607,7 +604,7 @@ mod octane_static_props {
#[pyo3(name = "get_specific_energy")]
#[staticmethod]
pub fn get_specific_energy_py(te_octane: f64) -> anyhow::Result<f64> {
Ok(Self::get_specific_energy(te_octane * uc::KELVIN - *uc::CELSIUS_TO_KELVIN)?.get::<si::joule_per_kilogram>())
Ok(Self::get_specific_energy((te_octane - uc::CELSIUS_TO_KELVIN) * uc::KELVIN )?.get::<si::joule_per_kilogram>())
}
/// Returns temperature [°C] of octane
Expand All @@ -616,7 +613,7 @@ mod octane_static_props {
#[pyo3(name = "get_te_from_u")]
#[staticmethod]
pub fn get_te_from_u_py(u: f64) -> anyhow::Result<f64> {
Ok(Self::get_te_from_u(u * uc::J_PER_KG)?.get::<si::kelvin>() - uc::CELSIUS_TO_KELVIN.value)
Ok(Self::get_te_from_u(u * uc::J_PER_KG)?.get::<si::degree_celsius>())
}
)]
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, HistoryMethods)]
Expand All @@ -629,7 +626,10 @@ impl Octane {
/// # Arguments
/// - `te_octane`: temperature of octane
pub fn get_specific_energy(te_octane: si::Temperature) -> anyhow::Result<si::SpecificEnergy> {
Ok(osp::ENERGY_INTERP.interpolate(&[te_octane.get::<si::kelvin>()])? * uc::J_PER_KG)
Ok(
osp::ENERGY_INTERP.interpolate(&[te_octane.get::<si::degree_celsius>()])?
* uc::J_PER_KG,
)
}

/// Returns temperature of octane
Expand Down
Loading

0 comments on commit 755f088

Please sign in to comment.