# Source code for topfarm.cost_models.economic_models.dtu_wind_cm_main

```"""
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

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"],
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] = {
"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"],
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] = {
"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())
```