"""
2018 - Created by Witold Skrzypinski, wisk@dtu.dk
Implementation of Offshore Turbine Cost Model, ref. Soeren Oemann Lind, soli@dtu.dk
Structure based on 2017 turbine_cost.py by Arvydas Berzonskis, Goldwind
"""
import numpy as np
import numpy_financial as npf
[docs]
class economic_evaluation():
'''All masses are in kg, all costs are in 2017 Euro'''
def __init__(self, distance_from_shore, energy_price, project_duration,
discount_rate=0.0909870634):
# Initialize dictionaries
self.project_costs = {}
self.project_costs_sums = {}
self.discount_rate = discount_rate # [-]
self.distance_from_shore = distance_from_shore # [km]
self.energy_price = energy_price # [Euro/kWh]
self.project_duration = project_duration # [years]
def calculate_npv(self, rated_rpm_array, D_rotor_array, Power_rated_array,
hub_height_array, water_depth_array, aep_array, cabling_cost=None):
'''
Calculate Net Present Value [Euro]
Input:
rated_rpm_array [RPM]
D_rotor_array [m]
Power_rated_array [MW]
hub_height_array [m]
aep_array [kWh]
water_depth_array [m]
'''
self.calculate_expenditures(
rated_rpm_array,
D_rotor_array,
Power_rated_array,
hub_height_array,
aep_array,
water_depth_array,
cabling_cost)
self.calculate_cash_flow()
self.NPV = npf.npv(self.discount_rate, self.CWF)
return self.NPV
def calculate_irr(self, rated_rpm_array, D_rotor_array, Power_rated_array,
hub_height_array, water_depth_array, aep_array, cabling_cost=None):
'''
Calculate Internal Rate of Return [%]
Input:
rated_rpm_array [RPM]
D_rotor_array [m]
Power_rated_array [MW]
hub_height_array [m]
aep_array [kWh]
water_depth_array [m]
'''
self.calculate_expenditures(
rated_rpm_array,
D_rotor_array,
Power_rated_array,
hub_height_array,
aep_array,
water_depth_array,
cabling_cost)
self.calculate_cash_flow()
self.IRR = 100 * npf.irr(self.CWF) # [%]
return self.IRR
def calculate_cash_flow(self):
'''Calculate cash flow every year during the project period'''
self.CWF = []
for i in range(self.project_duration + 1):
if i == 0:
self.CWF.append(float(-self.project_costs_sums["DEVEX"] - self.project_costs_sums["CAPEX"]))
elif i == self.project_duration:
self.CWF.append(float(self.energy_price * sum(self.aep_vector) - self.project_costs_sums["ABEX"] - self.project_costs_sums["OPEX"]))
else:
self.CWF.append(self.energy_price * sum(self.aep_vector) - self.project_costs_sums["OPEX"])
def calculate_expenditures(self, rated_rpm, rotor_diameter, rated_power,
hub_height, aep_array, water_depth, cabling_cost=None):
'''Calculate DEVEX, CAPEX, OPEX and ABEX [Euro]'''
# Ensure that the variables are numpy arrays
self.aep_vector = np.array(aep_array)
# Calculate expenditures
self.calculate_devex(rated_power)
self.calculate_capex(rated_rpm, rotor_diameter, rated_power,
hub_height, water_depth, cabling_cost)
self.calculate_opex(rated_power)
self.calculate_abex()
def calculate_devex(self, rated_power):
'''Calculate DEVEX [Euro]'''
rated_power = np.array(rated_power)
number_of_turbines = np.size(rated_power)
myName = "DEVEX"
magicFactor = 2.0e3 / 39 * 0.3 / 80
self.project_costs[myName] = {
"environmental_survey": magicFactor * 1e6 * self.distance_from_shore,
"sea_bed_survey": 1.5 * 1e5 * number_of_turbines,
"met_mast": magicFactor * 1e6 * self.distance_from_shore,
"development_services": 0.7 * 1e5 * np.sum(rated_power)}
self.project_costs_sums[myName] = sum(
self.project_costs[myName].values())
def calculate_capex(self, rated_rpm, rotor_diameter, rated_power,
hub_height, water_depth, cabling_cost=None):
'''Calculate CAPEX [Euro]'''
rated_rpm = np.array(rated_rpm)
rotor_diameter = np.array(rotor_diameter)
rated_power = np.array(rated_power)
hub_height = np.array(hub_height)
water_depth = np.array(water_depth)
self.calculate_turbine(
rated_rpm,
rotor_diameter,
rated_power,
hub_height)
self.calculate_foundation(rotor_diameter, rated_power, water_depth)
# %% BOP [Euro] (Balance of Plant costs)
myName = "BOP"
self.project_costs[myName] = {
"substation": 6.0e6 +
1.0e4 *
np.sum(rated_power) ** 1.5,
"array_of_cables": 3.5e3 *
np.sum(rotor_diameter),
"cables_export": 1.4e6 *
self.distance_from_shore,
"onshore_electrical": 5.0e4 *
np.sum(rated_power) +
50.0 *
np.sum(rated_power) ** 2.0}
if cabling_cost:
self.project_costs[myName]["array_of_cables"] = cabling_cost
self.project_costs_sums[myName] = sum(
self.project_costs[myName].values())
# %% CAPEX [Euro]
self.project_costs_sums["CAPEX"] = sum(
self.turbine_general_costs_sums["bill_of_material"]) + sum(
self.foundation_general_costs_sums["bill_of_material"]) + self.project_costs_sums["BOP"]
def calculate_opex(self, rated_power):
''' Calculate OPEX [Euro / year]'''
rated_power = np.array(rated_power)
number_of_turbines = np.size(rated_power)
myName = "O&M"
self.project_costs[myName] = {
"onshore personnel": 5.5e3 *
np.sum(rated_power),
"buildings, habor fees etc.": 3.0e6,
"mobilization, rental time": 9.6e4 *
number_of_turbines,
"jackup personnel": 8.5e3 *
number_of_turbines,
"offshore service personnel": 1.2e4 *
np.sum(rated_power),
"service, failed components": 2.1e3 *
np.sum(rated_power),
"ships, offhsore operations": 4.6e3 *
number_of_turbines *
self.distance_from_shore}
self.project_costs_sums[myName] = sum(
self.project_costs[myName].values())
self.project_costs_sums["OPEX"] = self.project_costs_sums["O&M"]
def calculate_abex(self):
''' Calculate ABEX [Euro]'''
self.project_costs_sums["ABEX"] = 0.03 * \
self.project_costs_sums["CAPEX"]
def calculate_turbine(
self,
rated_rpm,
rotor_diameter,
rated_power,
hub_height):
''' Calculate the part of CAPEX associated with the turbine itself [Euro]'''
self.turbine_component_mass = {}
self.turbine_component_mass_sums = {}
self.turbine_component_costs = {}
self.turbine_component_costs_sums = {}
self.turbine_general_costs = {}
self.turbine_general_costs_sums = {}
rated_torque = rated_power / (rated_rpm * np.pi / 30.0) * 1.1
rotor_area = np.pi * (rotor_diameter / 2) ** 2
# %% Blades
comp_name = "3_blades"
self.turbine_component_mass[comp_name] = 0.0 + \
0.3 * rotor_diameter ** 2.5
self.turbine_component_costs[comp_name] = 12.0 * \
self.turbine_component_mass[comp_name]
self.turbine_component_mass_sums[comp_name] = self.turbine_component_mass[comp_name]
self.turbine_component_costs_sums[comp_name] = self.turbine_component_costs[comp_name]
# %% Hub incl. pitch system w/ bearings
comp_name = "hub"
self.turbine_component_mass[comp_name] = {
"structure": 6.0e3 + 0.1 * rotor_diameter ** 2.5,
"pitch_bearings": 5.0e2 + 0.07 * rotor_diameter ** 2.5,
"pitch_system": 5.0e2 + 0.03 * rotor_diameter ** 2.5,
"secondary": 7.0e2 + 15.0 * rotor_diameter ** 1.0}
self.turbine_component_costs[comp_name] = {
"structure": 2.5 * self.turbine_component_mass[comp_name]["structure"],
"pitch_bearings": 8.0 * self.turbine_component_mass[comp_name]["pitch_bearings"],
"pitch_system": 8.0 * self.turbine_component_mass[comp_name]["pitch_system"],
"secondary": 8.0 * self.turbine_component_mass[comp_name]["secondary"]}
self.turbine_component_mass_sums[comp_name] = sum(
self.turbine_component_mass[comp_name].values())
self.turbine_component_costs_sums[comp_name] = sum(
self.turbine_component_costs[comp_name].values())
# %% High Speed Drivetrain
# self.high_speed_drivetrain(rotor_diameter, rated_torque, rated_rpm)
# %% Medium Speed Drivetrain
self.medium_speed_drivetrain(rotor_diameter, rated_torque, rated_rpm)
# %% Direct Drive Drivetrain
# self.direct_drive_drivetrain(rotor_diameter, rated_torque)
# %% Nacelle
comp_name = "nacelle"
self.turbine_component_mass[comp_name] = {
"cooling": 0.0 + 500.0 * rated_power ** 1.0,
"converter": 0.0 + 1.0e3 * rated_power ** 1.0,
"controller": 200.0 + 100.0 * rated_power ** 1.0,
"yaw": 0.0 + 0.1 * rotor_diameter ** 2.5,
"canopy": 1.0e3 + 1.5e3 * rated_power ** 1.0,
"secondary": 1.0e3 + 1.0e3 * rated_power ** 1.0}
self.turbine_component_costs[comp_name] = {
"cooling": 8.0 * self.turbine_component_mass[comp_name]["cooling"],
"converter": 30.0 * self.turbine_component_mass[comp_name]["converter"],
"controller": 50.0 * self.turbine_component_mass[comp_name]["controller"],
"yaw": 6.0 * self.turbine_component_mass[comp_name]["yaw"],
"canopy": 10.0 * self.turbine_component_mass[comp_name]["canopy"],
"secondary": 10.0 * self.turbine_component_mass[comp_name]["secondary"]}
self.turbine_component_mass_sums[comp_name] = sum(
self.turbine_component_mass[comp_name].values())
self.turbine_component_costs_sums[comp_name] = sum(
self.turbine_component_costs[comp_name].values())
# %% Tower
comp_name = "tower"
self.turbine_component_mass[comp_name] = {
"structure": 0.0 + 0.25 * (rotor_area * hub_height) ** 1.0,
"internal": 1.0e3 + 100.0 * hub_height ** 1.0,
"cabling": 0.0 + 25.0 * (rated_power * hub_height) ** 1.0,
"secondary": 1.0e3 + 500.0 * rated_power ** 1.0,
"transformer": 0.0 + 2.5e3 * rated_power ** 1}
self.turbine_component_costs[comp_name] = {
"structure": 1.5 * self.turbine_component_mass[comp_name]["structure"],
"internal": 8.0 * self.turbine_component_mass[comp_name]["internal"],
"cabling": 8.0 * self.turbine_component_mass[comp_name]["cabling"],
"secondary": 10.0 * self.turbine_component_mass[comp_name]["secondary"],
"transformer": 8.0 * self.turbine_component_mass[comp_name]["transformer"]}
self.turbine_component_mass_sums[comp_name] = sum(
self.turbine_component_mass[comp_name].values())
self.turbine_component_costs_sums[comp_name] = sum(
self.turbine_component_costs[comp_name].values())
# %% Turbine Bill of Material (BOM) cost
self.turbine_general_costs_sums["bill_of_material"] = sum(
self.turbine_component_costs_sums.values())
# %% Turbine Direct Production Cost
myName = "direct_production"
self.turbine_general_costs[myName] = {
"direct_labor": 0.03 *
self.turbine_general_costs_sums["bill_of_material"],
"production_overhead": 0.1 *
self.turbine_general_costs_sums["bill_of_material"]}
self.turbine_general_costs_sums[myName] = sum(self.turbine_general_costs[myName].values(
)) + self.turbine_general_costs_sums["bill_of_material"]
# %% Turbine Selling, General and Administrative Expenses (SG&A)
myName = "SG&A"
self.turbine_general_costs[myName] = {
"SG&A_overhead": 0.05 * (self.turbine_general_costs_sums["direct_production"]),
"R&D": 0.03 * (self.turbine_general_costs_sums["direct_production"]),
"SG&A": 0.05 * (self.turbine_general_costs_sums["direct_production"])}
self.turbine_general_costs_sums[myName] = sum(
self.turbine_general_costs[myName].values())
# %% Turbine Total Production Cost
self.turbine_general_costs_sums["total_production"] = self.turbine_general_costs_sums[
"direct_production"] + self.turbine_general_costs_sums["SG&A"]
# %% Turbine Project costs
myName = "project"
self.turbine_general_costs[myName] = {
"transportation": 0.2 * sum(self.turbine_component_mass_sums.values()) + 1.0e4,
"harbor_storage_and_assembly": 2.5e4 * rated_power + 1.5e5,
"installation_and_comissioning": 5.0e4 * rated_power + 1.0e5,
"warranty_and_accruals": 0.03 * self.turbine_general_costs_sums["total_production"],
"financing": 0.02 * self.turbine_general_costs_sums["total_production"]}
self.turbine_general_costs_sums[myName] = sum(
self.turbine_general_costs[myName].values())
# %% Turbine Total Cost
self.turbine_general_costs_sums["TOTAL"] = self.turbine_general_costs_sums["total_production"] + \
self.turbine_general_costs_sums["project"]
def calculate_foundation(self, rotor_diameter, rated_power, water_depth):
''' Calculate the part of CAPEX associated with the foundation itself [Euro]'''
# Initialize dictionaries
self.foundation_mass = {}
self.foundation_costs = {}
self.foundation_general_costs = {}
self.foundation_general_costs_sums = {}
# %% Foundation
self.foundation_mass = {
"monopile_incl_TP": (
6.5e4 +
4.5e3 *
water_depth +
40.0 *
water_depth**2) *
rated_power}
self.foundation_costs = {
"monopile_incl_TP": 1.5 * self.foundation_mass["monopile_incl_TP"]}
'''
self.foundation_mass = {
"jacket_incl_boat_landing" : ( 8.3e4 - 700.0 * water_depth + 110.0 * water_depth**2) * rated_power}
self.foundation_costs = {
"jacket_incl_boat_landing" : 2.4 * self.foundation_mass["jacket_incl_boat_landing"]}
'''
self.foundation_mass_sum = sum(self.foundation_mass.values())
self.foundation_cost_sum = sum(self.foundation_costs.values())
# %% Foundation Bill of Material (BOM) cost
self.foundation_general_costs_sums["bill_of_material"] = self.foundation_cost_sum
# %% Foundation Direct Production Cost
myName = "direct_production"
self.foundation_general_costs[myName] = {
"direct_labor": 0.03 *
self.foundation_general_costs_sums["bill_of_material"],
"material_overhead": 0.1 *
self.foundation_general_costs_sums["bill_of_material"]}
self.foundation_general_costs_sums[myName] = sum(self.foundation_general_costs[myName].values(
)) + self.foundation_general_costs_sums["bill_of_material"]
# %% Foundation Selling, General and Administrative Expenses (SG&A)
myName = "SG&A"
self.foundation_general_costs[myName] = {
"SG&A_overhead": 0.05 * (self.foundation_general_costs_sums["direct_production"]),
"R&D": 0.03 * (self.foundation_general_costs_sums["direct_production"]),
"SG&A": 0.05 * (self.foundation_general_costs_sums["direct_production"])}
self.foundation_general_costs_sums[myName] = sum(
self.foundation_general_costs[myName].values())
# %% Foundation Total Production Cost
self.foundation_general_costs_sums["total_production"] = self.foundation_general_costs_sums[
"direct_production"] + self.foundation_general_costs_sums["SG&A"]
# %% Foundation Project costs
myName = "project"
self.foundation_general_costs[myName] = {
"transportation": 0.15 *
self.foundation_general_costs_sums["total_production"],
"installation": 160.0 *
self.foundation_mass_sum ** 0.5 +
2.0e3 *
self.distance_from_shore,
"warranty_and_accruals": 0.03 *
self.foundation_general_costs_sums["total_production"],
"financing": 0.02 *
self.foundation_general_costs_sums["total_production"]}
self.foundation_general_costs_sums[myName] = sum(
self.foundation_general_costs[myName].values())
# %% Foundation Total Cost
self.foundation_general_costs_sums["TOTAL"] = self.foundation_general_costs_sums[
"total_production"] + self.foundation_general_costs_sums["project"]
def high_speed_drivetrain(self, rotor_diameter, rated_torque, rated_rpm):
'''Calculate the cost of high speed drivetrain [Euro]'''
comp_name = "hs_drivetrain"
self.turbine_component_mass[comp_name] = {
"bedplate": 0.0 + 2.4 * rotor_diameter ** 2.0,
"main_shaft": 0.0 + 0.02 * rotor_diameter ** 2.8,
"main_bearings": 0.0 + 0.02 * rotor_diameter ** 2.5,
"bearing_housing": 0.0 + 0.03 * rotor_diameter ** 2.5,
"gearbox": 0.0 + 15.0e3 * rated_torque ** 1.0,
"coupling_&_brake": 500.0 + 50.0 * (rated_torque * rated_rpm / 1.5) ** 1.0,
"generator": 1.0e3 + 400.0 * (rated_torque * rated_rpm / 1.5) ** 1.0}
self.turbine_component_costs[comp_name] = {
"bedplate": 2.5 *
self.turbine_component_mass[comp_name]["bedplate"],
"main_shaft": 5.0 *
self.turbine_component_mass[comp_name]["main_shaft"],
"main_bearings": 15.0 *
self.turbine_component_mass[comp_name]["main_bearings"],
"bearing_housing": 2.5 *
self.turbine_component_mass[comp_name]["bearing_housing"],
"gearbox": 8.0 *
self.turbine_component_mass[comp_name]["gearbox"],
"coupling_&_brake": 8.0 *
self.turbine_component_mass[comp_name]["coupling_&_brake"],
"generator": 8.0 *
self.turbine_component_mass[comp_name]["generator"]}
self.turbine_component_mass_sums[comp_name] = sum(
self.turbine_component_mass[comp_name].values())
self.turbine_component_costs_sums[comp_name] = sum(
self.turbine_component_costs[comp_name].values())
def medium_speed_drivetrain(self, rotor_diameter, rated_torque, rated_rpm):
'''Calculate the cost of medium speed drivetrain [Euro]'''
comp_name = "ms_drivetrain"
self.turbine_component_mass[comp_name] = {
"bedplate": 0.0 + 1.2 * rotor_diameter ** 2.0,
"main_shaft": 0.0 + 0.02 * rotor_diameter ** 2.8,
"main_bearings": 0.0 + 0.02 * rotor_diameter ** 2.5,
"bearing_housing": 0.0 + 0.03 * rotor_diameter ** 2.5,
"gearbox": 0.0 + 1.0e4 * rated_torque ** 1.0,
"coupling_&_brake": 0.0 + 30.0 * (rated_torque * rated_rpm / 0.4) ** 1.0,
"generator": 6.0e3 + 100.0 * (rated_torque * rated_rpm / 0.4) ** 1.0}
self.turbine_component_costs[comp_name] = {
"bedplate": 2.5 *
self.turbine_component_mass[comp_name]["bedplate"],
"main_shaft": 5.0 *
self.turbine_component_mass[comp_name]["main_shaft"],
"main_bearings": 15.0 *
self.turbine_component_mass[comp_name]["main_bearings"],
"bearing_housing": 2.5 *
self.turbine_component_mass[comp_name]["bearing_housing"],
"gearbox": 8.0 *
self.turbine_component_mass[comp_name]["gearbox"],
"coupling_&_brake": 8.0 *
self.turbine_component_mass[comp_name]["coupling_&_brake"],
"generator": 8.0 *
self.turbine_component_mass[comp_name]["generator"]}
self.turbine_component_mass_sums[comp_name] = sum(
self.turbine_component_mass[comp_name].values())
self.turbine_component_costs_sums[comp_name] = sum(
self.turbine_component_costs[comp_name].values())
def direct_drive_drivetrain(self, rotor_diameter, rated_torque):
'''Calculate the cost of direct drive drivetrain [Euro]'''
comp_name = "dd_drivetrain"
self.turbine_component_mass[comp_name] = {
"bedplate": 0.0 + 1.2 * rotor_diameter ** 2.0,
"generator": 0.0 + 35.0e3 * rated_torque ** 0.666666666667}
self.turbine_component_costs[comp_name] = {
"bedplate": 2.5 * self.turbine_component_mass[comp_name]["bedplate"],
"generator": 8.0 * self.turbine_component_mass[comp_name]["generator"]}
self.turbine_component_mass_sums[comp_name] = sum(
self.turbine_component_mass[comp_name].values())
self.turbine_component_costs_sums[comp_name] = sum(
self.turbine_component_costs[comp_name].values())