"""
turbine_costsse_2017.py

Created by Arvydas Berzonskis  Goldwind 2017 based on turbine_costsse_2015.py 2015.
Copyright (c) NREL. All rights reserved.
"""
import numpy as np
import math
import matplotlib.pyplot as plt
from openmdao.core.explicitcomponent import ExplicitComponent
plt.close("all")

# Rotor
# -------------------------------------------------------------------------------


class economic_evaluation():

    def __init__(self, D_rotor_array, Power_rated_array, hub_height_array, aep_array):
        self.D_rotor_array = D_rotor_array
        self.Power_rated_array = Power_rated_array
        self.hub_height_array = hub_height_array
        self.aep_array = aep_array

    def calculate_irr(self):

        #        blade_type_array = [''] * len(D_rotor_array)
        # turbine_type_array = list(map(lambda x, y: self.reflection_turbine_type(x, y),
        #                           D_rotor_array, Power_rated_array))
        # weight_array = list(map(lambda x: self.simple_weight_height_trans(x),
        #                     hub_height_array))

        # turbine_type_vector = [[item] for item in turbine_type_array]
        machine_rating = np.array([[int(item)] for item in self.Power_rated_array])
        rotor_diameter = np.array([[int(item)] for item in self.D_rotor_array])
        hub_height = np.array([[int(item)] for item in self.hub_height_array])
        # weight_vector = [[float(item)] for item in weight_array]
        aep_vector = np.array([[float(item)] for item in self.aep_array])

    # def __init__(self, rotor_diameter, machine_rating, hub_height, aep_vector):
        # calculate the blade mass and cost
        # Baseline mode
        self.blade_B_mass = 3 * 0.1452 * (rotor_diameter / 2)**2.9158  # all 3 blades
        # Advanced mode
        self.blade_A_mass = 0.4948 * (rotor_diameter / 2)**2.53  # all 3 blades
        # Blade material cost escalator
        self.BCE = 1
        # Labor cost escalator
        self.GDPE = 1
        # Costs
        self.blade_B_costs = 3 * ((0.4019 * (rotor_diameter / 2)**3 - 955.24) * self.BCE +
                                  2.7445 * (rotor_diameter / 2)**2.5025 * self.GDPE) / (1 - 0.28)
        self.blade_A_costs = 3 * ((0.4019 * (rotor_diameter / 2)**3 - 21051) * self.BCE +
                                  2.7445 * (rotor_diameter / 2)**2.5025 * self.GDPE) / (1 - 0.28)

        # calculate the Hub cost and weight
        self.hub_mass = 0.954 * (self.blade_B_mass / 3) + 5680.3
        self.hub_cost = self.hub_mass * 4.25

        # Pitch mechanisms and bearings
        self.pich_bearing_mass = 0.1295 * self.blade_B_mass + 491.31
        self.pitch_system_mass = self.pich_bearing_mass * 1.328 + 555
        # Total pitch costs
        self.pitch_system_cost = 2.28 * (0.2106 * rotor_diameter**2.6578)  # All 3 blades

        # Spinner, nose cone
        self.nose_cone_mass = 18.5 * rotor_diameter - 520.5
        self.nose_cone_cost = self.nose_cone_mass * 5.57

        # Low-speed shaft
        ''' Notes might not be used for direct drive turbine costs'''
        self.low_speed_shaft_mass = 0.0142 * rotor_diameter**2.888
        self.low_speed_shaft_cost = 0.01 * rotor_diameter**2.887

        # Main bearings
        self.bearing_mass = (rotor_diameter * 8 / 600 - 0.033) * 0.0092 * rotor_diameter**2.5
        self.bearing_cost = 2 * self.bearing_mass * 17.6

        # Mecahnical brake, high-speed coupling and associated components
        self.brake_and_coupling_cost = 1.9894 * machine_rating - 0.1141
        self.brake_and_coupling_mass = self.brake_and_coupling_cost / 10.

        # Direct drive Generator
        # self.generator_mass=661.25*self.low_speed_shaft_torque**0.606
        self.generator_cost = machine_rating * 219.33

        # Variable-speed electronics
        self.variablespeed_electronics = machine_rating * 79.

        # Yaw Drive and Bearing
        self.yaw_system_mass = 1.6 * (0.00098 * rotor_diameter**3.314)
        self.yaw_system_cost = 2 * (0.0339 * rotor_diameter**2.964)

        # Mainframe - Direct Drive
        self.mainframe_mass = 1.228 * rotor_diameter**1.953
        self.mainframe_cost = 627.28 * rotor_diameter**0.85

        # Platforms and railings
        self.platform_railing_mass = 0.125 * self.mainframe_mass
        self.platform_railing_cost = self.platform_railing_mass * 8.7

        # Electrical connections
        self.electrical_connection_cost = machine_rating * 40.

        # Hydraulic and Cooling Systems
        self.hydraulic_cooling_system_mass = 0.08 * machine_rating
        self.hydraulic_cooling_system_cost = machine_rating * 12

        # Nacelle Cover
        self.nacelle_cost = 11.537 * machine_rating + 3849.7
        self.nacelle_mass = self.nacelle_cost / 10.

        # Control, Safety Sytem, Condition Monitoring
        self.control_cost = 35000.0

        # Tower
        # Baseline model
        self.tower_B_mass = 0.3973 * (math.pi * (rotor_diameter / 2)**2) * hub_height - 1414
        # Advanced model
        self.tower_A_mass = 0.2694 * (math.pi * (rotor_diameter / 2)**2) * hub_height - 1779
        self.tower_cost = self.tower_B_mass * 1.5

        # Foundation cost
        self.foundation_cost = 303.24 * (hub_height * (math.pi * (rotor_diameter / 2))**2)**0.4037

        # Transportation cost
        self.trasport_coeff = 1.581e-5 * machine_rating**2 - 0.0375 * machine_rating + 54.7
        self.trasport_cost = machine_rating * self.trasport_coeff

        # Roads and Civil work
        self.roads_civil_cost_fact = 2.17e-6 * machine_rating**2 - 0.0145 * machine_rating + 69.54
        self.roads_civil_cost_cost = self.roads_civil_cost_fact * machine_rating

        # Assembly and Installation
        self.assembly_and_installation_cost = 1.965 * (hub_height * rotor_diameter)**1.1736

        # Electrical Interface and connections
        self.electrical_interface_fact = 3.49e-6 * machine_rating**2 - 0.0221 * machine_rating + 109.7
        self.electrical_interface_cost = machine_rating * self.electrical_interface_fact

        # Annual operating expenses - AOE
        self.LCC = 0.00108 * sum(aep_vector)
        self.OandM = 0.007 * sum(aep_vector)
        self.LRC = sum(10.7 * machine_rating)
        self.AOE = self.LCC + (self.OandM + self.LRC) / sum(aep_vector)

        # I do not know how to calculate the weight
        # self.variable_speed_elec_mass_cost=18.8*variable_speed_elec_mass

        self.cost = 1.33 * (self.blade_B_costs + self.hub_cost + self.pitch_system_cost + self.nose_cone_cost + self.bearing_cost +
                            self.brake_and_coupling_cost + self.generator_cost + self.variablespeed_electronics + self.yaw_system_cost +
                            self.mainframe_cost + self.platform_railing_cost + self.electrical_connection_cost +
                            self.hydraulic_cooling_system_cost + self.nacelle_cost + self.control_cost + self.tower_cost +
                            self.foundation_cost + self.trasport_cost + self.roads_civil_cost_cost + self.assembly_and_installation_cost +
                            self.electrical_interface_cost)  # the ratio of 1.33 is to account for inflation since 2003.

        self.CWF = []

        for i in range(1, 20):
            if i == 1:
                self.CWF.append(int(0.1 * sum(aep_vector) - sum(self.cost) - self.AOE))
            else:
                self.CWF.append(int(0.1 * sum(aep_vector) - self.AOE))

        self.IRR = 100 * np.irr(self.CWF)
        return self.IRR


def main():
    if __name__ == '__main__':
        Drotor_vector = np.array([121.0, 115.0, 121.0, 121.0, 121.0, 121.0, 121.0, 121.0, 121.0, 121.0, 121.0, 121.0, 121.0, 121.0,
                                  121.0, 121.0, 121.0, 121.0, 121.0, 121.0, 121.0, 121.0, 121.0, 115.0])
        power_rated_vector = np.array([2000., 2000., 2000., 2000., 2000., 2000., 2000., 2000., 2000., 2000., 2000., 2000.,
                                       2000., 2000., 2000., 2000., 2000., 2000., 2000., 2000., 2000., 2000., 2000., 2000.])
        hub_height_vector = np.array([105., 105., 105., 105., 105., 105., 105., 105., 105., 105., 105., 105., 105., 105.,
                                      105., 105., 105., 105., 105., 105., 105., 105., 105., 105.])
        aep_vector = np.array([7719409.76158781, 7703877.645459095, 6034197.878645113, 6494510.809393061, 8147512.144511054,
                               7369147.974147366, 8681084.747836143, 7147269.951808259, 6141634.901501132, 5682294.113683184,
                               6859259.383656042, 7447180.72443833, 5761350.543959712, 6755014.03150229, 6337664.079841179,
                               5151511.151202235, 5456811.610073241, 6722954.6423807535, 7185180.112344236, 7215858.2123201955,
                               7136356.084546783, 6267802.418413456, 5899094.2746176915, 6592877.854876981])
        # initialize class
        Turbine = economic_evaluation(Drotor_vector, power_rated_vector, hub_height_vector, aep_vector)  # Rotor diameter; Power rated; Hub Height
        # run the method for IRR calculations
        Turbine.calculate_irr()

        print('Wind turbine configuration costs', Turbine.cost)
        print('IRR', Turbine.IRR)

    #    fig,ax = plt.subplots()
    #    ax.plot(Drotor_vector,economic_evaluation.cost)
    #    ax.set(xlabel='Rotor diameter [m]', ylabel='Initial costs [$]')

        # just the cost bar lot
        barplotvector = np.array([Turbine.blade_B_costs[0], Turbine.hub_cost[0], Turbine.pitch_system_cost[0], Turbine.nose_cone_cost[0],
                                  Turbine.bearing_cost[0], Turbine.brake_and_coupling_cost[0], Turbine.generator_cost[0],
                                  Turbine.variablespeed_electronics[0], Turbine.yaw_system_cost[0], Turbine.mainframe_cost[0],
                                  Turbine.platform_railing_cost[0], Turbine.electrical_connection_cost[0],
                                  Turbine.hydraulic_cooling_system_cost[0], Turbine.nacelle_cost[0], 35000,
                                  Turbine.tower_cost[0], Turbine.foundation_cost[0], Turbine.trasport_cost[0], Turbine.roads_civil_cost_cost[0],
                                  Turbine.assembly_and_installation_cost[0], Turbine.electrical_interface_cost[0]] / Turbine.cost[0])
        N = 21
        ind = np.arange(N)  # the x locations for the groups
        width = 0.5       # the width of the bars

        plt.rcParams.update({'figure.autolayout': True})
        fig, ax = plt.subplots()
        bar = ax.barh(ind, barplotvector, width, color='b')

        # add some text for labels, title and axes ticks
        ax.set_xlabel('Procentage of total costs [%]')
        ax.set_title('Wind turbine components costs')
        ax.set_yticks(ind + width / 2)
        ax.set_yticklabels(('Blades', 'Hub', 'Pitch System', 'Nose cone', 'Bearing', 'Break and coupling', 'Generator',
                            'Variable speed electornics', 'Yaw system', 'Mainframe', 'Platform railing', 'Electical connections',
                            'Hydraulic cooling systems', 'Nacelle cover', 'Control', 'Tower', 'Foundation', 'Transportation',
                            'Roads', 'Assembly and installation', 'Electrical interface'))
        labels = ax.get_xticklabels()
        plt.setp(labels, rotation=45, horizontalalignment='right')
        plt.show()


main()
