from copy import deepcopy
from time import perf_counter
from pprint import pprint
import yaml
import numpy as np
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt
from wombat.core import Simulation
from wombat.core.library import IEA_26, load_yaml
pd.set_option("display.max_rows", 1000)
pd.set_option("display.max_columns", 1000)
%matplotlib inline
tech_salary_annual = 100000
techs = 30
capacity = 400 * 1000 # 400MW -> kW
tech_salary_annual * techs / capacity
7.5
configs = [
"one_mobilization",
"one_mobilization_100pct_reduction",
"two_mobilizations",
"two_mobilizations_100pct_reduction",
"three_mobilizations",
"three_mobilizations_100pct_reduction",
]
columns = deepcopy(configs)
results = {
"availability - time based": [],
"availability - production based": [],
"capacity factor - net": [],
"capacity factor - gross": [],
"power production": [],
"task completion rate": [],
"total annual costs": [],
"technicians": [],
"materials": [],
"vessels": [],
"ctv cost": [],
"hlv cost": [],
"dsv cost": [],
"cab cost": [],
"manual reset": [],
"minor repair": [],
"major repair": [],
"major replacement": [],
"remote reset": [],
"annual service": [],
"bos": [], # substructure inspection + scour repair + substation inspection + small/large transformer repairs
"total downtime": [],
"ctv utilization": [],
"hlv utilization": [],
"dsv utilization": [],
"cab utilization": [],
}
for config in configs:
# Run the simulation
start = perf_counter()
sim = Simulation(IEA_26, f"{config}.yaml")
sim.run()
end = perf_counter()
print(f"{sim.config.name.rjust(45)} | {(end - start) / 60:.2f} m")
# Gather the results of interest
years = sim.metrics.events.year.unique().shape[0]
mil = 1000000
availability = sim.metrics.time_based_availability(frequency="project", by="windfarm")
availability_production = sim.metrics.production_based_availability(frequency="project", by="windfarm")
cf_net = sim.metrics.capacity_factor(which="net", frequency="project", by="windfarm")
cf_gross = sim.metrics.capacity_factor(which="gross", frequency="project", by="windfarm")
power_production = sim.metrics.power_production(frequency="project", by_turbine=False).values[0][0]
completion_rate = sim.metrics.task_completion_rate(which="both", frequency="project")
parts = sim.metrics.events[["materials_cost"]].sum().sum()
techs = sim.metrics.project_fixed_costs(frequency="project", resolution="medium").labor[0]
total = sim.metrics.events[["total_cost"]].sum().sum()
equipment = sim.metrics.equipment_costs(frequency="project", by_equipment=True)
equipment_sum = equipment.sum().sum()
ctv = equipment[[el for el in equipment.columns if "Crew Transfer Vessel" in el]].sum().sum()
hlv = equipment[[el for el in equipment.columns if "Jack-up Vessel" in el]].sum().sum()
dsv = equipment[[el for el in equipment.columns if "Diving Support Vessel" in el]].sum().sum()
cab = equipment[[el for el in equipment.columns if "Cable Laying Vessel" in el]].sum().sum()
times = sim.metrics.process_times()
times = times / years / 24 / 100 # events per turbine and year
utilization = sim.metrics.service_equipment_utilization(frequency="project")
ctv_ur = utilization[[el for el in utilization.columns if "Crew Transfer Vessel" in el]].mean().mean()
hlv_ur = utilization[[el for el in utilization.columns if "Jack-up Vessel" in el]].mean().mean()
dsv_ur = utilization[[el for el in utilization.columns if "Diving Support Vessel" in el]].mean().mean()
cab_ur = utilization[[el for el in utilization.columns if "Cable Laying Vessel" in el]].mean().mean()
# Log the results of interest
results["availability - time based"].append(availability)
results["availability - production based"].append(availability_production)
results["capacity factor - net"].append(cf_net)
results["capacity factor - gross"].append(cf_gross)
results["power production"].append(power_production)
results["task completion rate"].append(completion_rate)
results["total annual costs"].append((total + techs) / mil / years)
results["technicians"].append(techs / mil / years)
results["materials"].append(parts / mil / years)
results["vessels"].append(equipment_sum / mil / years)
results["ctv cost"].append(ctv / mil / years)
results["hlv cost"].append(hlv / mil / years)
results["dsv cost"].append(dsv / mil / years)
results["cab cost"].append(cab / mil / years)
results["manual reset"].append(times.loc[times.index.intersection(["manual reset"]), "downtime"].sum())
results["minor repair"].append(times.loc[times.index.intersection(["minor repair", ]), "downtime"].sum())
results["major repair"].append(times.loc[times.index.intersection(["major repair"]), "downtime"].sum())
results["major replacement"].append(times.loc[times.index.intersection(["major replacement"]), "downtime"].sum())
results["remote reset"].append(times.loc[times.index.intersection(["remote reset"]), "downtime"].sum())
results["annual service"].append(times.loc[times.index.intersection(["annual service"]), "downtime"].sum())
ix = [
"substructure inspection", "substation inspection",
"small foundation/scour repair", "cable replacement",
"small transformer repair", "large transformer repair"
]
results["bos"].append(times.loc[times.index.intersection(ix), "downtime"].sum())
results["total downtime"].append(times.loc[:, "downtime"].sum())
results["ctv utilization"].append(ctv_ur)
results["hlv utilization"].append(hlv_ur)
results["dsv utilization"].append(dsv_ur)
results["cab utilization"].append(cab_ur)
sim.env.cleanup_log_files(log_only=True)
iea_26_one_mobilization | 5.58 m iea_26_one_mobilization_100pct_reduction | 5.86 m iea_26_two_mobilizations | 6.58 m iea_26_two_mobilizations_100pct_reduction | 6.78 m iea_26_three_mobilizations | 7.36 m iea_26_three_mobilizations_100pct_reduction | 7.31 m
# Save the results
# pickled dictionary format
with open(IEA_26/ "outputs" / "results_dict_v0.4.yaml", "w") as f:
yaml.dump(results, f, default_flow_style=False, sort_keys=False)
# dataframe/csv format
results_df = pd.DataFrame(results.values(), columns=columns, index=results.keys()).fillna(0)
results_df.to_csv(IEA_26 / "outputs" / "results_data_v0.4.csv", index_label="result")
pd.options.display.float_format = '{:,.2f}'.format
results_df
one_mobilization | one_mobilization_100pct_reduction | two_mobilizations | two_mobilizations_100pct_reduction | three_mobilizations | three_mobilizations_100pct_reduction | |
---|---|---|---|---|---|---|
availability - time based | 0.66 | 0.65 | 0.90 | 0.86 | 0.96 | 0.91 |
availability - production based | 0.67 | 0.65 | 0.91 | 0.86 | 0.96 | 0.92 |
capacity factor - net | 0.39 | 0.38 | 0.53 | 0.51 | 0.57 | 0.54 |
capacity factor - gross | 0.59 | 0.59 | 0.59 | 0.59 | 0.59 | 0.59 |
power production | 27,533,472,037.00 | 26,832,956,757.50 | 37,498,176,059.00 | 35,577,459,635.50 | 39,785,891,398.50 | 37,830,990,928.00 |
task completion rate | 0.99 | 1.00 | 0.99 | 1.00 | 0.99 | 1.00 |
total annual costs | 15.35 | 14.95 | 21.34 | 20.97 | 24.84 | 24.42 |
technicians | 3.00 | 3.00 | 3.00 | 3.00 | 3.00 | 3.00 |
materials | 4.14 | 3.76 | 6.16 | 5.83 | 6.61 | 6.38 |
vessels | 8.22 | 8.19 | 12.18 | 12.14 | 15.23 | 15.03 |
ctv cost | 2.56 | 2.56 | 2.56 | 2.56 | 2.56 | 2.56 |
hlv cost | 3.59 | 3.56 | 7.54 | 7.51 | 10.60 | 10.40 |
dsv cost | 0.53 | 0.53 | 0.54 | 0.53 | 0.53 | 0.53 |
cab cost | 1.55 | 1.55 | 1.55 | 1.55 | 1.55 | 1.55 |
manual reset | 0.27 | 4.62 | 0.26 | 9.19 | 0.29 | 8.99 |
minor repair | 0.48 | 2.34 | 0.55 | 3.64 | 0.55 | 3.68 |
major repair | 0.54 | 0.74 | 0.65 | 0.94 | 0.69 | 0.94 |
major replacement | 88.43 | 81.64 | 30.48 | 27.51 | 9.74 | 8.23 |
remote reset | 0.20 | 2.42 | 0.23 | 3.22 | 0.24 | 3.34 |
annual service | 1.68 | 0.00 | 1.52 | 0.00 | 1.39 | 0.00 |
bos | 0.17 | 2.28 | 0.04 | 3.71 | 0.01 | 2.97 |
total downtime | 91.87 | 94.10 | 33.84 | 48.29 | 13.00 | 28.22 |
ctv utilization | 0.04 | 0.03 | 0.05 | 0.00 | 0.00 | 0.04 |
hlv utilization | 0.02 | 0.02 | 0.02 | 0.00 | 0.00 | 0.01 |
dsv utilization | 0.00 | 0.00 | 0.03 | 0.00 | 0.00 | 0.01 |
cab utilization | 0.02 | 0.01 | 0.01 | 0.00 | 0.00 | 0.01 |