{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Code-to-Code Comparison: Dinwoodie\n", "\n", "### National Renewable Energy Laboratory\n", "\n", "#### Rob Hammond\n", "\n", "##### 27 May 2021" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "tags": [] }, "outputs": [], "source": [ "import os\n", "import pickle\n", "from copy import deepcopy\n", "from time import perf_counter\n", "from pprint import pprint\n", "from pathlib import Path\n", "\n", "import numpy as np\n", "import pandas as pd\n", "import networkx as nx\n", "import matplotlib.pyplot as plt\n", "\n", "from wombat.core import Simulation, Metrics\n", "from wombat.core.library import DINWOODIE, load_yaml\n", "\n", "pd.set_option(\"display.max_rows\", 1000)\n", "pd.set_option(\"display.max_columns\", 1000)\n", "pd.options.display.float_format = '{:,.2f}'.format\n", "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "'6.6667'" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Converting Labor values to fixed cost input for the base case\n", "tech_salary_annual = 80000\n", "techs = 20\n", "capacity = 240 * 1000 # 240 -> kW\n", "f\"{tech_salary_annual * techs / capacity:.4f}\"" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "tags": [] }, "outputs": [], "source": [ "configs = [\n", " \"base\",\n", " \"more_ctvs\",\n", " \"fewer_ctvs\",\n", " \"more_techs\",\n", " \"fewer_techs\",\n", " \"failure_50\",\n", " \"failure_200\",\n", " \"no_hlvs\",\n", " \"no_weather\",\n", " \"historic_weather\",\n", " \"manual_resets_only\",\n", " \"minor_repairs_only\",\n", " \"medium_repairs_only\",\n", " \"major_repairs_only\",\n", " \"major_replacements_only\",\n", " \"annual_service_only\",\n", "]\n", "columns = deepcopy(configs)\n", "results = {\n", " \"availability - time based\": [],\n", " \"availability - production based\": [],\n", " \"capacity factor - net\": [],\n", " \"capacity factor - gross\": [],\n", " \"power production\": [],\n", " \"task completion rate\": [],\n", " \"annual direct O&M cost\": [],\n", " \"annual vessel cost\": [],\n", " \"ctv cost\": [],\n", " \"fsv cost\": [],\n", " \"hlv cost\": [],\n", " \"annual repair cost\": [],\n", " \"annual technician cost\": [],\n", " \"ctv utilization\": [],\n", " \"fsv utilization\": [],\n", " \"hlv utilization\": [],\n", " \n", "}" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " dinwoodie_base | 0.48 min\n" ] } ], "source": [ "for config in configs:\n", " # Run the simulation\n", " start = perf_counter()\n", " sim = Simulation(library_path=DINWOODIE, config=f\"{config}.yaml\")\n", " print(f\"{sim.config.name.rjust(30)}\", end=\" | \")\n", " sim.run(8760)\n", " end = perf_counter()\n", " print(f\"{(end - start) / 60:.2f} min\")\n", " \n", " events_fname = Path(sim.env.events_log_fname)\n", " fname = events_fname.name\n", " fname = fname.replace(\"_events.log\", \"_metrics_inputs.yaml\")\n", "\n", " # Get the path and move it 1 level up to /outputs/\n", " fpath = events_fname.parents[1]\n", " metrics = Metrics.from_simulation_outputs(fpath, fname)\n", " \n", " # Gather the results of interest\n", " years = metrics.events.year.unique().shape[0]\n", " mil = 1000000\n", " \n", " availability_time = metrics.time_based_availability(frequency=\"project\", by=\"windfarm\")\n", " availability_production = metrics.production_based_availability(frequency=\"project\", by=\"windfarm\")\n", " cf_net = metrics.capacity_factor(which=\"net\", frequency=\"project\", by=\"windfarm\")\n", " cf_gross = metrics.capacity_factor(which=\"gross\", frequency=\"project\", by=\"windfarm\")\n", " power_production = metrics.power_production(frequency=\"project\", by_turbine=False).values[0][0]\n", " completion_rate = metrics.task_completion_rate(which=\"both\", frequency=\"project\")\n", " parts = metrics.events[[\"materials_cost\"]].sum().sum()\n", " techs = metrics.project_fixed_costs(frequency=\"project\", resolution=\"low\").operations[0]\n", " total = metrics.events[[\"total_cost\"]].sum().sum()\n", " \n", " equipment = metrics.equipment_costs(frequency=\"project\", by_equipment=True)\n", " equipment_sum = equipment.sum().sum()\n", " hlv = equipment[[el for el in equipment.columns if \"Heavy Lift Vessel\" in el]].sum().sum()\n", " fsv = equipment[[el for el in equipment.columns if \"Field Support Vessel\" in el]].sum().sum()\n", " ctv = equipment[[el for el in equipment.columns if \"Crew Transfer Vessel\" in el]].sum().sum()\n", " \n", " utilization = metrics.service_equipment_utilization(frequency=\"project\")\n", " hlv_ur = utilization[[el for el in utilization.columns if \"Heavy Lift Vessel\" in el]].mean().mean()\n", " fsv_ur = utilization[[el for el in utilization.columns if \"Field Support Vessel\" in el]].mean().mean()\n", " ctv_ur = utilization[[el for el in utilization.columns if \"Crew Transfer Vessel\" in el]].mean().mean()\n", " \n", " # Log the results of interest\n", " results[\"availability - time based\"].append(availability_time)\n", " results[\"availability - production based\"].append(availability_production)\n", " results[\"capacity factor - net\"].append(cf_net)\n", " results[\"capacity factor - gross\"].append(cf_gross)\n", " results[\"power production\"].append(power_production)\n", " results[\"task completion rate\"].append(completion_rate)\n", " results[\"annual direct O&M cost\"].append((total + techs) / mil / years)\n", " results[\"annual vessel cost\"].append(equipment_sum / mil / years)\n", " results[\"ctv cost\"].append(ctv / mil / years)\n", " results[\"fsv cost\"].append(fsv / mil / years)\n", " results[\"hlv cost\"].append(hlv / mil / years)\n", " results[\"annual repair cost\"].append(parts / mil / years)\n", " results[\"annual technician cost\"].append(techs / mil / years)\n", " results[\"ctv utilization\"].append(ctv_ur)\n", " results[\"fsv utilization\"].append(fsv_ur)\n", " results[\"hlv utilization\"].append(hlv_ur)\n", " break" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "# Save the results\n", "# pickled dictionary format\n", "# with open(os.path.join(str(DINWOODIE), \"outputs\", \"results_dict.pkl\"), \"wb\") as f:\n", "# pickle.dump(results, f)\n", "\n", "# dataframe/csv format\n", "results_df = pd.DataFrame(results.values(), columns=[columns[0]], index=results.keys()).fillna(0)\n", "# results_df.to_csv(os.path.join(str(DINWOODIE), \"outputs\", \"results_data.csv\"), index_label=\"result\")" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
base
availability - time based0.98
availability - production based0.97
capacity factor - net0.41
capacity factor - gross0.42
power production859,422,410.50
task completion rate0.99
annual direct O&M cost14.58
annual vessel cost10.43
ctv cost1.92
fsv cost0.27
hlv cost8.25
annual repair cost2.55
annual technician cost1.60
ctv utilization0.65
fsv utilization0.17
hlv utilization0.46
\n", "
" ], "text/plain": [ " base\n", "availability - time based 0.98\n", "availability - production based 0.97\n", "capacity factor - net 0.41\n", "capacity factor - gross 0.42\n", "power production 859,422,410.50\n", "task completion rate 0.99\n", "annual direct O&M cost 14.58\n", "annual vessel cost 10.43\n", "ctv cost 1.92\n", "fsv cost 0.27\n", "hlv cost 8.25\n", "annual repair cost 2.55\n", "annual technician cost 1.60\n", "ctv utilization 0.65\n", "fsv utilization 0.17\n", "hlv utilization 0.46" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "results_df" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "# start = perf_counter()\n", "# sim = Simulation(library_path=DINWOODIE, config=\"base.yaml\")\n", "# print(f\"{sim.config.name.rjust(30)}\", end=\" | \")\n", "# sim.run()\n", "# end = perf_counter()\n", "# print(f\"{(end - start) / 60:.2f} min\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.8" } }, "nbformat": 4, "nbformat_minor": 4 }