Skip to content

Commit

Permalink
fixed (hopefully) bug into temperature-dependent engine efficiency
Browse files Browse the repository at this point in the history
  • Loading branch information
calbaker committed Jan 31, 2025
1 parent ccd8067 commit 4d8d49c
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 33 deletions.
13 changes: 7 additions & 6 deletions cal_and_val/thermal/cal_hev.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ def get_exp_pwr_hvac(df):

## Constraint functions
def get_fc_temp_too_hot(sd_dict):
te_fc_deg_c = sd_dict['veh']['pt_type']['HybridElectricVehicle']['fc']['thrml']['FuelConverterThermal']['state']['temperature_kelvin'] + celsius_to_kelvin_offset
te_fc_deg_c = sd_dict['veh']['pt_type']['HybridElectricVehicle']['fc']['thrml']['FuelConverterThermal']['state']['temperature_kelvin'] - celsius_to_kelvin_offset
if np.any(te_fc_deg_c > 115):
return 1
else:
Expand Down Expand Up @@ -513,11 +513,12 @@ def get_fc_temp_too_hot(sd_dict):
(10, 100), # new_fc_thrml_htc_to_amb_stop_watts_per_square_meter_kelvin,
(10, 1000), # new_fc_thrml_conductance_from_comb_watts_per_kelvin,
# (), # new_fc_thrml_max_frac_from_comb,
(3, 20), # new_fc_thrml_radiator_effectiveness,
(220, 380), # new_fc_thrml_fc_eff_model_Exponential_offset,
(3, 200), # new_fc_thrml_radiator_effectiveness,
(220, 300), # new_fc_thrml_fc_eff_model_Exponential_offset,
(10, 60), # new_fc_thrml_fc_eff_model_Exponential_lag,
(0.15, 0.35), # new_fc_thrml_fc_eff_model_Exponential_minimum,
),
# TODO: make `constr_fns` accept both `sd_dict` and `df`
constr_fns=(
get_fc_temp_too_hot,
),
Expand Down Expand Up @@ -564,13 +565,13 @@ def perturb_params(pos_perturb_dec: float = 0.05, neg_perturb_dec: float = 0.1):
print("Verifying that model responds to input parameter changes by individually perturbing parameters")
baseline_errors = cal_mod_obj.get_errors(
cal_mod_obj.update_params(baseline_params)
)
)[0]

for i, param in enumerate(baseline_params):
# +5%
perturbed_params = baseline_params.copy()
perturbed_params[i] = param * (1 + pos_perturb_dec)
perturbed_errors = cal_mod_obj.get_errors(cal_mod_obj.update_params(perturbed_params))
perturbed_errors = cal_mod_obj.get_errors(cal_mod_obj.update_params(perturbed_params))[0]
if np.all(perturbed_errors == baseline_errors):
print("\nperturbed_errros:")
pprint.pp(perturbed_errors)
Expand All @@ -582,7 +583,7 @@ def perturb_params(pos_perturb_dec: float = 0.05, neg_perturb_dec: float = 0.1):
# -5%
perturbed_params = baseline_params.copy()
perturbed_params[i] = param * (1 - neg_perturb_dec)
perturbed_errors = cal_mod_obj.get_errors(cal_mod_obj.update_params(perturbed_params))
perturbed_errors = cal_mod_obj.get_errors(cal_mod_obj.update_params(perturbed_params))[0]
if np.all(perturbed_errors == baseline_errors):
print("\nperturbed_errros:")
pprint.pp(perturbed_errors)
Expand Down
2 changes: 1 addition & 1 deletion cal_and_val/thermal/val_hev.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
:len(cal_mod_obj.param_fns)].to_numpy()

# getting the solved models
(errors_cal, sds_cal) = cal_mod_obj.get_errors(
(errors_cal, cvs_cal, sds_cal) = cal_mod_obj.get_errors(
sim_drives=cal_mod_obj.update_params(param_vals_fuel_energy),
return_mods=True,
)
Expand Down
26 changes: 10 additions & 16 deletions fastsim-core/src/vehicle/powertrain/fuel_converter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,6 @@ impl FuelConverter {
)
);
self.state.pwr_prop = pwr_out_req;
// TODO: make this temperature dependent
self.state.eff = if fc_on {
uc::R
* self
Expand Down Expand Up @@ -772,17 +771,12 @@ impl FuelConverterThermal {
offset,
lag,
minimum,
}) => ((1.0
- f64::exp({
(-1.0 / {
let exp_denom: si::Ratio =
(lag / uc::KELVIN) * (self.state.temperature - offset);
exp_denom
})
.get::<si::ratio>()
}))
* uc::R)
.max(minimum),
}) => {
let dte: si::TemperatureInterval = (self.state.temperature.get::<si::kelvin_abs>()
- offset.get::<si::kelvin_abs>())
* uc::KELVIN_INT;
((1.0 - f64::exp((-dte / lag).get::<si::ratio>())) * uc::R).max(minimum)
}
};
Ok(())
}
Expand Down Expand Up @@ -931,18 +925,18 @@ impl Default for FCTempEffModelLinear {
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
pub struct FCTempEffModelExponential {
/// temperature at which `fc_eta_temp_coeff` begins to grow
pub offset: si::TemperatureInterval,
pub offset: si::Temperature,
/// exponential lag parameter [K^-1]
pub lag: f64,
pub lag: si::TemperatureInterval,
/// minimum value that `fc_eta_temp_coeff` can take
pub minimum: si::Ratio,
}

impl Default for FCTempEffModelExponential {
fn default() -> Self {
Self {
offset: 0.0 * uc::KELVIN_INT,
lag: 25.0,
offset: 0.0 * uc::KELVIN,
lag: 25.0 * uc::KELVIN_INT,
minimum: 0.2 * uc::R,
}
}
Expand Down
22 changes: 12 additions & 10 deletions python/fastsim/pymoo_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Module containing functions and classes for easy interaction with PyMOO
"""
import numpy as np
import pprint
import numpy.typing as npt
from typing import Tuple, Any, List, Callable, Dict, Optional, Union
from pathlib import Path
Expand Down Expand Up @@ -123,14 +124,15 @@ def new_peak_res_eff (sd_dict, new_peak_eff) -> Dict:

# calculated in __post_init__
n_obj: Optional[int] = None
n_constr: Optional[int] = None

def __post_init__(self):
assert self.n_obj is None, "`n_obj` is not intended to be user provided"
assert len(self.dfs) == len(
self.models), f"{len(self.dfs)} != {len(self.models)}"
assert len(self.bounds) == len(self.param_fns)
self.n_obj = len(self.models) * len(self.obj_fns)
self.n_obj = len(self.models) * len(self.constr_fns)
self.n_constr = len(self.models) * len(self.constr_fns)

def update_params(self, xs: List[Any]):
"""
Expand Down Expand Up @@ -190,11 +192,10 @@ def get_errors(
key: str
df_exp: pd.DataFrame

if not isinstance(sd, fsim.SimDrive):
solved_mods[key] = sd
objectives[key] = [1.0e12] * len(self.obj_fns)
constraint_violations[key] = [1] * len(self.constr_fns)
continue
# if not isinstance(sd, fsim.SimDrive):
# solved_mods[key] = sd
# objectives[key] = [1.0e12] * len(self.obj_fns)
# continue

try:
t0 = time.perf_counter()
Expand Down Expand Up @@ -239,7 +240,6 @@ def get_errors(

if not walk_success:
objectives[key].append(1.02e12)
constraint_violations[key].append(1)
else:
try:
objectives[key].append(get_error_val(
Expand All @@ -266,6 +266,9 @@ def get_errors(
t2 = time.perf_counter()
if self.verbose:
print(f"Time to postprocess: {t2 - t1:.3g} s")
# print("\nobjectives:")
# pprint.pp(objectives)
# print("")
if return_mods:
return objectives, constraint_violations, solved_mods
else:
Expand All @@ -287,7 +290,6 @@ def __init__(
self,
mod_obj: ModelObjectives,
elementwise_runner=LoopedElementwiseEvaluation(),
n_constr: int=0,
):
self.mod_obj = mod_obj
assert len(self.mod_obj.bounds) == len(
Expand All @@ -300,15 +302,15 @@ def __init__(
xu=[bounds[1]
for bounds in self.mod_obj.bounds],
elementwise_runner=elementwise_runner,
n_ieq_constr=n_constr,
n_ieq_constr=self.mod_obj.n_constr,
)

def _evaluate(self, x, out, *args, **kwargs):
sim_drives = self.mod_obj.update_params(x)
(errs, cvs) = self.mod_obj.get_errors(sim_drives)
out['F'] = list(errs.values())
if self.n_ieq_constr > 0:
out['G'] = list(cvs.values())
out['G'] = list(cvs.values())

class CustomOutput(Output):
def __init__(self):
Expand Down

0 comments on commit 4d8d49c

Please sign in to comment.