Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/KTH-dESA/MJ2383 into main
Browse files Browse the repository at this point in the history
  • Loading branch information
willu47 committed Aug 23, 2021
2 parents 5cb4b5d + faf7d60 commit 0f34b3d
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 47 deletions.
68 changes: 37 additions & 31 deletions MJ2383_Lab_1.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"import pandas as pd\n",
"import ipywidgets as widgets\n",
"from ipywidgets import interact, fixed\n",
"from checkers import checker_crf, checker_lcoe, checker_parameters"
"from checkers import checker_df, checker_lcoe, checker_parameters"
]
},
{
Expand Down Expand Up @@ -231,13 +231,13 @@
"\n",
"According to [OEE](http://www.open-electricity-economics.org/book/text/03.html) the formula to calculate LCOE is as follows:\n",
"\n",
"\\\\(LCOE = \\frac{C_{fix} + \\sum_{y=1}^Y CRF_y \\cdot C_y}{\\sum_{y=1}^Y CRF_y \\cdot G_y}\\\\)\n",
"\\\\(LCOE = \\frac{C_{fix} + \\sum_{y=1}^Y DF_y \\cdot C_y}{\\sum_{y=1}^Y DF_y \\cdot G_y}\\\\)\n",
"\n",
"where LCOE is the levelized cost in EUR per kWh, \\\\(C_{fix}\\\\) is the capital investment costs incurred for setting up the project, \\\\(C_y\\\\) are operational costs incurred in year \\\\(y\\\\), \\\\(Y\\\\) is the technical lifetime in years, and \\\\(G_y\\\\) is electricity generation in kWh. The costs are called levelized because they are “leveled” over all units of output. Levelized costs can be calculated for a specific power plant or for generic types of generation technologies.\n",
"\n",
"Capital recovery factor (CRF) is calculated for each year \\\\(y\\\\) of the plant's technical lifetime\n",
"Discount factor (DF) is calculated for each year \\\\(y\\\\) of the plant's technical lifetime\n",
"\n",
"\\\\(CRF_y = (1 + r)^{-y}\\\\)\n",
"\\\\(DF_y = (1 + r)^{-y}\\\\)\n",
"\n",
"where r is the discount rate"
]
Expand Down Expand Up @@ -297,10 +297,10 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we calculate CRF for each year in our plant's technical lifetime according to the formula we saw earlier:\n",
"\\\\(CRF_y = (1 + r)^{-y}\\\\); \\\\(r\\\\) is the discount rate, and \\\\(y\\\\) is the year.\n",
"Now we calculate DF for each year in our plant's technical lifetime according to the formula we saw earlier:\n",
"\\\\(DF_y = (1 + r)^{-y}\\\\); \\\\(r\\\\) is the discount rate, and \\\\(y\\\\) is the year.\n",
"\n",
"**Implement the CRF formula in the cell below. Remember that to exponentiate in Python we use** `**`.\n",
"**Implement the DF formula in the cell below. Remember that to exponentiate in Python we use** `**`.\n",
"\n",
"**Q. What happens if you change the discount rate?**"
]
Expand All @@ -312,8 +312,8 @@
"outputs": [],
"source": [
"discount_rate = 0.05\n",
"crf = \"replace me with the CRF formula\"\n",
"print(crf) # we use the command print, to show the values stored inside the crf variable"
"df = \"replace me with the DF formula\"\n",
"print(df) # we use the command print, to show the values stored inside the df variable"
]
},
{
Expand All @@ -323,14 +323,14 @@
"outputs": [],
"source": [
"# Run this cell to check your answer\n",
"checker_crf(crf, discount_rate, year)"
"checker_df(df, discount_rate, year)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we've calculated CRF, let's get some data for the other parameters:"
"Now we've calculated DF, let's get some data for the other parameters:"
]
},
{
Expand All @@ -354,7 +354,7 @@
"\n",
"Remember the formula? Let's check it again:\n",
"\n",
"\\\\(LCOE = \\frac{C_{fix} + \\sum_{y=1}^Y CRF_y \\cdot C_y}{\\sum_{y=1}^Y CRF_y \\cdot G_y}\\\\)\n",
"\\\\(LCOE = \\frac{C_{fix} + \\sum_{y=1}^Y DF_y \\cdot C_y}{\\sum_{y=1}^Y DF_y \\cdot G_y}\\\\)\n",
"\n",
"Now, implement the LCOE formula in the cell below:"
]
Expand Down Expand Up @@ -448,7 +448,7 @@
"If you managed to get it to work, well done! You've written a Python function which computes LCOE. If not, don't worry, the answer is below! Make sure to write it in the function so the following steps of the Lab work.\n",
"\n",
"- In this stage, we introduced the LCOE equation\n",
"\\\\(LCOE = \\frac{C_{fix} + \\sum_{y=1}^Y CRF_y \\cdot C_y}{\\sum_{y=1}^Y CRF_y \\cdot G_y}\\\\)\n",
"\\\\(LCOE = \\frac{C_{fix} + \\sum_{y=1}^Y DF_y \\cdot C_y}{\\sum_{y=1}^Y DF_y \\cdot G_y}\\\\)\n",
"and implemented it using a Python function.\n",
"- We also explored how the capital recovery factors weighs future years differently as a function of the discount rate.\n",
"- We learnt a lot of Python concepts including *variables*, *arrays*, and *arguments*.\n",
Expand All @@ -458,12 +458,12 @@
"\n",
"### Stage 1 - Answer LCOE Function\n",
"\n",
"As you can see, we just need to fill in the gaps. First build the array of years, calculate the array of CRF and then add the lcoe calculation.\n",
"As you can see, we just need to fill in the gaps. First build the array of years, calculate the array of DF and then add the lcoe calculation.\n",
"```python\n",
"def get_lcoe(capital_costs, operational_costs, electricity_generation, discount_rate, technical_lifetime):\n",
" year = np.arange(technical_lifetime)\n",
" crf = (1 + discount_rate) ** - year\n",
" lcoe = (capital_costs + sum(crf * operational_costs)) / sum(crf * electricity_generation)\n",
" df = (1 + discount_rate) ** - year\n",
" lcoe = (capital_costs + sum(df * operational_costs)) / sum(df * electricity_generation)\n",
" return lcoe\n",
"```"
]
Expand Down Expand Up @@ -591,7 +591,8 @@
"metadata": {},
"outputs": [],
"source": [
"def get_lcoe_input(station_size, overnight_cost, fuel_efficiency, fuel_price, fixed_om_cost, load_factor):\n",
"def get_lcoe_input(station_size, overnight_cost, fuel_efficiency, \n",
" fuel_price, fixed_om_cost, load_factor, variable_om_cost):\n",
" \"\"\"Calculates the input parameters for the lcoe function\n",
" \n",
" Arguments\n",
Expand All @@ -608,6 +609,8 @@
" The fixed operation and maintenance cost of the technology in €/kW\n",
" load_factor : float\n",
" The percentage of the year in which the technology generates electricity in %.\n",
" variable_om_cost : float\n",
" The variable operation and maintenance cost of the technology in €/kW\n",
" \n",
" Returns\n",
" -------\n",
Expand All @@ -630,7 +633,9 @@
" capital_cost = station_size * overnight_cost\n",
" total_fixed_om_cost = station_size * fixed_om_cost\n",
" annual_electricity_generation = station_size * HOURS_IN_YEAR * load_factor\n",
" total_variable_om_cost = (annual_electricity_generation / fuel_efficiency) * fuel_price\n",
"\n",
" total_variable_om_cost = ((annual_electricity_generation / fuel_efficiency) * fuel_price) + \\\n",
" (annual_electricity_generation * variable_om_cost)\n",
" annual_operational_cost = total_fixed_om_cost + total_variable_om_cost\n",
" \n",
" return {'capital_cost': capital_cost, 'total_fixed_om_cost': total_fixed_om_cost,\n",
Expand All @@ -645,7 +650,7 @@
"outputs": [],
"source": [
"def extended_lcoe(station_size, overnight_cost, fuel_efficiency, fuel_price, fixed_om_cost, load_factor, \n",
" discount_rate, technical_lifetime):\n",
" discount_rate, technical_lifetime, var_om_cost):\n",
" \"\"\"Calculates levelised cost of electricity as a function of useful parameters\n",
" \n",
" Arguments\n",
Expand All @@ -666,14 +671,16 @@
" A decimal value less than 1\n",
" technical_lifetime : int\n",
" Technical lifetime of the technology in years\n",
" var_om_cost : float\n",
" Variable operational and maintenance cost\n",
" \n",
" Returns\n",
" -------\n",
" float\n",
" The levelised cost of electricity in €/kWh\n",
" \"\"\"\n",
" lcoe_params = get_lcoe_input(station_size, overnight_cost, fuel_efficiency, \n",
" fuel_price, fixed_om_cost, load_factor)\n",
" fuel_price, fixed_om_cost, load_factor, var_om_cost)\n",
"\n",
" value = get_lcoe(lcoe_params['capital_cost'], lcoe_params['annual_operational_cost'], \n",
" lcoe_params['annual_electricity_generation'], discount_rate, \n",
Expand All @@ -695,7 +702,7 @@
"outputs": [],
"source": [
"ccgt_lcoe = extended_lcoe(capacity, overnight_cost, efficiency, fuel_price, fixed_om_cost, 0.75, \n",
" discount_rate, lifetime)\n",
" discount_rate, lifetime, 0.003)\n",
"ccgt_lcoe"
]
},
Expand All @@ -720,9 +727,8 @@
"metadata": {},
"outputs": [],
"source": [
"interact(extended_lcoe, station_size=fixed(750000), overnight_cost=(300, 1200), fuel_efficiency=(0.3, 0.7, 0.05), \n",
" fuel_price=(0.01, 0.10, 0.01), fixed_om_cost=(1, 5, 0.5), load_factor=(0.01, 1.0, 0.1), \n",
" discount_rate=(0.01, 0.30, 0.01), technical_lifetime=(10, 40, 1))"
"interact(extended_lcoe, station_size=(100000,750000, 10000), overnight_cost=(300, 2000), fuel_efficiency=(0.3, 0.7, 0.01), fuel_price=(0.00 , 0.20, 0.01), fixed_om_cost=(1, 50, 0.001), load_factor=(0.01, 1.0, 0.01), \n",
" discount_rate=(0.01, 0.30, 0.01), technical_lifetime=(10, 60, 1), var_om_cost=(0.0, 0.011, 0.001))"
]
},
{
Expand Down Expand Up @@ -793,14 +799,14 @@
" observation['LCOE'] = lcoe\n",
" \n",
" year = np.arange(technical_lifetime)\n",
" total_crf = sum((1 + discount_rate) ** - year)\n",
" total_df = sum((1 + discount_rate) ** - year)\n",
" \n",
" observation['Fixed OM Cost'] = (total_crf * lcoe_params['total_fixed_om_cost']) / \\\n",
" (total_crf * lcoe_params['annual_electricity_generation'])\n",
" observation['Variable OM Cost'] = (total_crf * lcoe_params['total_variable_om_cost']) / \\\n",
" (total_crf * lcoe_params['annual_electricity_generation'])\n",
" observation['Fixed OM Cost'] = (total_df * lcoe_params['total_fixed_om_cost']) / \\\n",
" (total_df * lcoe_params['annual_electricity_generation'])\n",
" observation['Variable OM Cost'] = (total_df * lcoe_params['total_variable_om_cost']) / \\\n",
" (total_df * lcoe_params['annual_electricity_generation'])\n",
" observation['Capital Cost'] = lcoe_params['capital_cost'] / \\\n",
" (total_crf * lcoe_params['annual_electricity_generation'])\n",
" (total_df * lcoe_params['annual_electricity_generation'])\n",
"\n",
" results.append(observation)\n",
" \n",
Expand Down Expand Up @@ -947,7 +953,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
"version": "3.8.5-final"
}
},
"nbformat": 4,
Expand Down
32 changes: 16 additions & 16 deletions checkers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@
import sys
from IPython.display import display, Markdown, Latex

def checker_crf(value, discount_rate, year):
crf = (1 + discount_rate) ** -year
def checker_df(value, discount_rate, year):
df = (1 + discount_rate) ** -year
if isinstance(value, np.ndarray):
if len(value) != len(year):
return print("The length of your array should be the same as the number of years.")
elif sum(crf == value) == len(crf):
elif sum(df == value) == len(df):
return print("Your answer is correct!")
else:
return print("The values provided are not correct. They should be:\n{}".format(
crf
df
))
else:
return display(Markdown("The argument `crf` needs to be of type `np.array()`"))
return display(Markdown("The argument `df` needs to be of type `np.array()`"))


def checker_lcoe(
Expand All @@ -28,9 +28,9 @@ def checker_lcoe(
try:
if isinstance(value, float):
year = np.arange(technical_lifetime)
crf = (1 + discount_rate) ** -year
lcoe = (capital_costs + sum(crf * operational_costs)) / sum(
crf * electricity_generation
df = (1 + discount_rate) ** -year
lcoe = (capital_costs + sum(df * operational_costs)) / sum(
df * electricity_generation
)
if value == lcoe:
return print("Your answer is correct!")
Expand All @@ -41,13 +41,13 @@ def checker_lcoe(
except:
return print("Unexpected error: {}".format(sys.exc_info()[0]))
raise


def checker_parameters(
el_gen,
op_costs,
capacity,
load_factor,
el_gen,
op_costs,
capacity,
load_factor,
fixed_om_cost,
fuel_price,
efficiency
Expand All @@ -56,7 +56,7 @@ def checker_parameters(
annual_fixed_om_cost = capacity * fixed_om_cost # in €
annual_variable_om_cost = fuel_price * electricity_generation / efficiency # in €
operational_costs = annual_fixed_om_cost + annual_variable_om_cost # in €

try:
if el_gen == electricity_generation:
str_out = 'Your electricity generation is correct!\n'
Expand All @@ -68,6 +68,6 @@ def checker_parameters(
str_out += f'Your operational costs are not right... they should be {operational_costs}'
return print(str_out)
except:
return print("Unexpected error: {}".format(sys.exc_info()[0]),
return print("Unexpected error: {}".format(sys.exc_info()[0]),
'Make sure your electricity generation and operational values are of type float')
raise

0 comments on commit 0f34b3d

Please sign in to comment.