Skip to content

Commit

Permalink
trying ot add constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
calbaker committed Jan 31, 2025
1 parent df5fc7e commit ccd8067
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 15 deletions.
31 changes: 27 additions & 4 deletions cal_and_val/thermal/cal_hev.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,15 @@ def get_mod_pwr_fuel(sd_dict):
def get_exp_pwr_fuel(df):
return df[fuel_column] * lhv_joules_per_gram

def get_mod_energy_fuel(sd_dict):
return np.array(sd_dict['veh']['pt_type']['HybridElectricVehicle']['fc']['history']['energy_fuel_joules'])

def get_exp_energy_fuel(df):
pwr_fuel_watts = df[fuel_column] * lhv_joules_per_gram
dt = np.diff(df[time_column], prepend=0)
energy_fuel_joules = np.cumsum(pwr_fuel_watts * dt)
return energy_fuel_joules

def get_mod_pwr_hvac(sd_dict):
return np.array(sd_dict['veh']['hvac']['LumpedCabin']['history']['pwr_aux_for_hvac_watts'])

Expand All @@ -398,6 +407,14 @@ def get_exp_pwr_hvac(df):
pwr_hvac = df["HVAC_Power_Hioki_P3[W]"]
return pwr_hvac

## 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
if np.any(te_fc_deg_c > 115):
return 1
else:
return -1

save_path = Path(__file__).parent / "pymoo_res" / Path(__file__).stem
save_path.mkdir(exist_ok=True, parents=True)

Expand All @@ -410,6 +427,10 @@ def get_exp_pwr_hvac(df):
get_mod_soc,
get_exp_soc
),
(
get_mod_energy_fuel,
get_exp_energy_fuel
),
(
get_mod_pwr_fuel,
get_exp_pwr_fuel
Expand Down Expand Up @@ -497,13 +518,12 @@ def get_exp_pwr_hvac(df):
(10, 60), # new_fc_thrml_fc_eff_model_Exponential_lag,
(0.15, 0.35), # new_fc_thrml_fc_eff_model_Exponential_minimum,
),
constr_fns=(
get_fc_temp_too_hot,
),
verbose=False,
)

print("")
pprint.pp(cal_mod_obj.params_and_bounds())
print("")

val_mod_obj = deepcopy(cal_mod_obj)
val_mod_obj.dfs = dfs_for_val
val_mod_obj.models = sds_for_val
Expand Down Expand Up @@ -574,6 +594,9 @@ def perturb_params(pos_perturb_dec: float = 0.05, neg_perturb_dec: float = 0.1):
print("Success!")

if __name__ == "__main__":
print("")
pprint.pp(cal_mod_obj.params_and_bounds())
print("")
perturb_params()
parser = pymoo_api.get_parser()
args = parser.parse_args()
Expand Down
18 changes: 14 additions & 4 deletions cal_and_val/thermal/val_hev.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,24 @@
from cal_hev import cal_mod_obj, val_mod_obj, save_path, time_column, mps_per_mph, speed_column, cyc_files_dict, cell_temp_column

res_df = pd.read_csv(save_path / "pymoo_res_df.csv")
res_df_fuel_energy = res_df.filter(regex="get_mod_energy_fuel")
res_df_fuel_energy_summed = res_df.filter(regex="get_mod_energy_fuel").sum(1)
best_row_fuel_energy = res_df_fuel_energy_summed.argmin()
param_vals_fuel_energy = res_df.iloc[
best_row_fuel_energy,
:len(cal_mod_obj.param_fns)].to_numpy()

res_df['euclidean'] = (
res_df.iloc[:, len(cal_mod_obj.param_fns):] ** 2).sum(1).pow(1/2)
best_row = res_df["euclidean"].argmin()
best_df = res_df.iloc[best_row, :]
param_vals = res_df.iloc[best_row, : len(cal_mod_obj.param_fns)].to_numpy()
param_vals_euclidean = res_df.iloc[
best_row,
:len(cal_mod_obj.param_fns)].to_numpy()

# getting the solved models
(errors_cal, sds_cal) = cal_mod_obj.get_errors(
sim_drives=cal_mod_obj.update_params(param_vals),
sim_drives=cal_mod_obj.update_params(param_vals_fuel_energy),
return_mods=True,
)
# (errors_val, sds_val) = val_mod_obj.get_errors(
Expand All @@ -32,8 +41,9 @@
for obj_fn in cal_mod_obj.obj_fns:
fig, ax = plt.subplots(2, 1, sharex=True)
cell_temp = next(iter(
[v[cell_temp_column] for k, v in cyc_files_dict.items() if k.replace(".txt", "") == key]
))
[v[cell_temp_column]
for k, v in cyc_files_dict.items() if k.replace(".txt", "") == key]
))
fig.suptitle(f"{key}\ncell temp [*C]: {cell_temp}")
ax[0].plot(
sd_cal['veh']['history']['time_seconds'],
Expand Down
29 changes: 22 additions & 7 deletions python/fastsim/pymoo_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ def new_peak_res_eff (sd_dict, new_peak_eff) -> Dict:
obj_fns: Tuple[Callable] | Tuple[Tuple[Callable, Callable]]
param_fns: Tuple[Callable]
bounds: Tuple[Tuple[float, float]]
constr_fns: Tuple[Callable]

# if True, prints timing and misc info
verbose: bool = False
Expand All @@ -129,6 +130,7 @@ def __post_init__(self):
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)

def update_params(self, xs: List[Any]):
"""
Expand Down Expand Up @@ -180,6 +182,7 @@ def get_errors(
"""

objectives: Dict = {}
constraint_violations: Dict = {}
solved_mods: Dict = {}

# loop through all the provided trips
Expand All @@ -189,7 +192,8 @@ def get_errors(

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

try:
Expand All @@ -209,6 +213,8 @@ def get_errors(
print(f"Time to simulate {key}: {t1 - t0:.3g}")

objectives[key] = []
constraint_violations[key] = []

if return_mods:
solved_mods[key] = sd_dict

Expand All @@ -232,7 +238,8 @@ def get_errors(
# TODO: provision for incomplete simulation in here somewhere

if not walk_success:
objectives[key].append(0.99e12)
objectives[key].append(1.02e12)
constraint_violations[key].append(1)
else:
try:
objectives[key].append(get_error_val(
Expand All @@ -247,18 +254,22 @@ def get_errors(
# NOTE: instead of appending an arbitrarily large
# objective value, we could instead either try passing
# `np.nan` or trigger a constraint violation.
objectives[key].append(1e12)
objectives[key].append(1.03e12)
else:
raise Exception("this is here for debugging and should be deleted")
objectives[key].append(mod_sig)
for constr_fn in self.constr_fns:
constraint_violations[key].append(
constr_fn(sd_dict)
)

t2 = time.perf_counter()
if self.verbose:
print(f"Time to postprocess: {t2 - t1:.3g} s")
if return_mods:
return objectives, solved_mods
return objectives, constraint_violations, solved_mods
else:
return objectives
return objectives, constraint_violations

def params_and_bounds(self):
return [
Expand All @@ -276,6 +287,7 @@ 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 @@ -288,13 +300,16 @@ def __init__(
xu=[bounds[1]
for bounds in self.mod_obj.bounds],
elementwise_runner=elementwise_runner,
n_ieq_constr=n_constr,
)

def _evaluate(self, x, out, *args, **kwargs):
sim_drives = self.mod_obj.update_params(x)
out['F'] = list(self.mod_obj.get_errors(sim_drives).values())
(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())


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

0 comments on commit ccd8067

Please sign in to comment.