├── HUE_system.py ├── OFFICE_system.py ├── README.md ├── SMTR_system.py ├── TSP_SMARTX_CONFIG_simple.py └── TSP_SMARTX_MAIN.py /HUE_system.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @author: TSP 5 | """ 6 | 7 | import TSP_SMARTX_CONFIG_simple as config 8 | 9 | ############################################################################### 10 | # CONSTANTS # 11 | ############################################################################### 12 | 13 | ### DUTY CYCLE ### 14 | DUTY_CYCLE_SA_LOW = 0.99 # units : [/] sleep time over active time 15 | DUTY_CYCLE_SA_MEAS = 0 # units : [/] sleep time over active time 16 | 17 | ### PHILIPS HUE SYSTEM ### 18 | POWER_HUE_HUB_SLEEP_SPECS = 0.10 # units : W | source : Philips HUE website, datasheet 19 | POWER_HUE_HUB_ACTIVE_SPECS = 1.25 # units : W | source : Philips HUE website, datasheet 20 | POWER_HUE_HUB_SLEEP_MEAS = 1e6 #-float('inf')# units : W | source : measurements DMM7510 21 | POWER_HUE_HUB_ACTIVE_MEAS = 1.29 # units : W | source : measurements DMM7510 22 | 23 | POWER_HUE_LIGHT_SLEEP_LOW = 0.4 # units : W | source : Philips HUE website, datasheet 24 | POWER_HUE_LIGHT_SLEEP_TYPICAL = 0.5 # units : W | source : Philips HUE website, datasheet 25 | POWER_HUE_LIGHT_SLEEP_HIGH = 0.5 # units : W | source : Philips HUE website, datasheet 26 | 27 | E_EM_OS_LOW = 7.092 # units : MJ 28 | E_EM_OS_TYPICAL = 9.59 29 | E_EM_OS_HIGH = 11.61 30 | 31 | E_EM_BULB_LOW = 4.32 32 | E_EM_BULB_TYPICAL = 11.94 33 | E_EM_BULB_HIGH = 13.45 34 | 35 | E_EM_HUB_LOW = 26.57 36 | E_EM_HUB_TYPICAL = 39.21 37 | E_EM_HUB_HIGH = 57.82 38 | 39 | E_MAINT = 0 40 | 41 | E_RECYCLING = 0 42 | 43 | E_RAW_MATERIALS = 0 44 | 45 | 46 | AAA_BATTERY_POWER_CAPACITY = 1.87 # units : Wh 47 | 48 | LIFETIME_LED = 25e3 # units hours 49 | LIFETIME_CFL = 10e3 # units hours 50 | LIFETIME_INC = 1e3 # units hours 51 | 52 | G_START_FSOLVE = 0.234 53 | 54 | ############################################################################### 55 | # FUNCTIONS # 56 | ############################################################################### 57 | 58 | def get_E_RawMaterials(scenario): 59 | 60 | if (scenario == 'LOW'): 61 | Erm = E_RAW_MATERIALS 62 | 63 | elif(scenario == 'BENCHMARK'): 64 | Erm = E_RAW_MATERIALS 65 | 66 | elif(scenario == 'HIGH'): 67 | Erm = E_RAW_MATERIALS 68 | 69 | else: 70 | raise NameError 71 | 72 | return Erm*1e6 # units = J 73 | 74 | def get_E_Embodied(ARGS, scenario): 75 | 76 | number_os, number_bulbs, number_hubs = ARGS 77 | 78 | if (scenario == 'LOW'): 79 | 80 | Eem_os = E_EM_OS_LOW 81 | Eem_bulbs = E_EM_BULB_LOW 82 | Eem_hubs = E_EM_HUB_LOW 83 | 84 | elif(scenario == 'BENCHMARK'): 85 | 86 | Eem_os = E_EM_OS_TYPICAL 87 | Eem_bulbs = E_EM_BULB_TYPICAL 88 | Eem_hubs = E_EM_HUB_TYPICAL 89 | 90 | elif(scenario == 'HIGH'): 91 | 92 | Eem_os = E_EM_OS_HIGH 93 | Eem_bulbs = E_EM_BULB_HIGH 94 | Eem_hubs = E_EM_HUB_HIGH 95 | 96 | else: 97 | raise NameError 98 | 99 | Eem = number_os*Eem_os + number_bulbs*Eem_bulbs + number_hubs*Eem_hubs # units : MJ 100 | 101 | return Eem*1e6 # units = J 102 | 103 | def get_E_Operation(ARGS, scenario): 104 | "Output = energy in JOULES for ONE year" 105 | 106 | number_os, number_bulbs, number_hubs = ARGS 107 | 108 | if (scenario == 'LOW'): 109 | Eop_os = 0 110 | Eop_bulbs = POWER_HUE_LIGHT_SLEEP_LOW*config.CONVERSION_YEAR_to_HOURS/1000*config.CONVERSION_kWh_to_MJ 111 | Eop_hubs = (DUTY_CYCLE_SA_LOW*POWER_HUE_HUB_SLEEP_SPECS + (1-DUTY_CYCLE_SA_LOW)*POWER_HUE_HUB_ACTIVE_SPECS)*config.CONVERSION_YEAR_to_HOURS/1000*config.CONVERSION_kWh_to_MJ 112 | 113 | elif(scenario == 'BENCHMARK'): 114 | Eop_os = 0 115 | Eop_bulbs = POWER_HUE_LIGHT_SLEEP_TYPICAL*config.CONVERSION_YEAR_to_HOURS/1000*config.CONVERSION_kWh_to_MJ 116 | Eop_hubs = (DUTY_CYCLE_SA_MEAS*POWER_HUE_HUB_SLEEP_MEAS + (1-DUTY_CYCLE_SA_MEAS)*POWER_HUE_HUB_ACTIVE_MEAS)*config.CONVERSION_YEAR_to_HOURS/1000*config.CONVERSION_kWh_to_MJ 117 | 118 | elif(scenario == 'HIGH'): 119 | Eop_os = 0 120 | Eop_bulbs = POWER_HUE_LIGHT_SLEEP_HIGH*config.CONVERSION_YEAR_to_HOURS/1000*config.CONVERSION_kWh_to_MJ 121 | Eop_hubs = (DUTY_CYCLE_SA_MEAS*POWER_HUE_HUB_SLEEP_MEAS + (1-DUTY_CYCLE_SA_MEAS)*POWER_HUE_HUB_ACTIVE_MEAS)*config.CONVERSION_YEAR_to_HOURS/1000*config.CONVERSION_kWh_to_MJ 122 | 123 | else: 124 | raise NameError 125 | 126 | Eop = number_os*Eop_os + number_bulbs*Eop_bulbs + number_hubs*Eop_hubs # units : MJ 127 | 128 | return Eop*1e6 # units = J 129 | 130 | def get_E_Maintenance(T_replacement, ARGS, scenario): 131 | 132 | number_os, number_bulbs, number_hubs = ARGS 133 | 134 | if (scenario == 'LOW'): 135 | Em = number_bulbs*E_EM_BULB_LOW/T_replacement 136 | 137 | elif(scenario == 'BENCHMARK'): 138 | Em = number_bulbs*E_EM_BULB_TYPICAL/T_replacement 139 | 140 | elif(scenario == 'HIGH'): 141 | Em = number_bulbs*E_EM_BULB_HIGH/T_replacement 142 | 143 | else: 144 | raise NameError 145 | 146 | Em = Em*1 # energy "equivalent" over one year 147 | 148 | if (T_replacement < 0): Em = 0 149 | 150 | return Em*1e6 # units : J 151 | 152 | 153 | def get_E_EoL(scenario): 154 | 155 | if (scenario == 'LOW'): 156 | Er = E_RECYCLING 157 | 158 | elif(scenario == 'BENCHMARK'): 159 | Er = E_RECYCLING 160 | 161 | elif(scenario == 'HIGH'): 162 | Er = E_RECYCLING 163 | 164 | else: 165 | raise NameError 166 | 167 | return Er*1e6 # units : J -------------------------------------------------------------------------------- /OFFICE_system.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @author: TSP 5 | """ 6 | 7 | import TSP_SMARTX_CONFIG_simple as config 8 | 9 | ############################################################################### 10 | # CONSTANTS # 11 | ############################################################################### 12 | 13 | 14 | LIFETIME_LIGHT = 25e3 # units : hours 15 | 16 | DUTY_CYCLE_SA = 0 17 | POWER_HUB_MEAN = 2.5 18 | POWER_NODE_MEAN = 0.025 19 | POWER_SENSOR_MEAN = 0.25 20 | 21 | E_EM_OS_LOW = 7.092 # units : MJ 22 | E_EM_OS_TYPICAL = 9.59 23 | E_EM_OS_HIGH = 11.61 24 | 25 | E_EM_BULB_LOW = 4.32 26 | E_EM_BULB_TYPICAL = 11.94 27 | E_EM_BULB_HIGH = 13.45 28 | 29 | E_EM_HUB_LOW = 26.57 30 | E_EM_HUB_TYPICAL = 39.21 31 | E_EM_HUB_HIGH = 57.82 32 | 33 | E_MAINT = 0 34 | 35 | E_RECYCLING = 0 36 | 37 | E_RAW_MATERIALS = 0 38 | 39 | G_START_FSOLVE = 0.234 40 | 41 | ############################################################################### 42 | # FUNCTIONS # 43 | ############################################################################### 44 | 45 | 46 | def get_E_RawMaterials(scenario): 47 | 48 | if (scenario == 'LOW'): 49 | Erm = 0 50 | 51 | elif(scenario == 'BENCHMARK'): 52 | Erm = 0 53 | 54 | elif(scenario == 'HIGH'): 55 | Erm = 0 56 | 57 | else: 58 | raise NameError 59 | 60 | return Erm*1e6 # units : J 61 | 62 | def get_E_Embodied(ARGS, scenario): 63 | 64 | number_os, number_nodes, number_hubs = ARGS 65 | 66 | if (scenario == 'LOW'): 67 | 68 | Eem_os = E_EM_OS_LOW 69 | Eem_nodes = E_EM_BULB_LOW 70 | Eem_hubs = E_EM_HUB_LOW 71 | 72 | elif(scenario == 'BENCHMARK'): 73 | 74 | Eem_os = E_EM_OS_TYPICAL 75 | Eem_nodes = E_EM_BULB_TYPICAL 76 | Eem_hubs = E_EM_HUB_TYPICAL 77 | 78 | elif(scenario == 'HIGH'): 79 | 80 | Eem_os = E_EM_OS_HIGH 81 | Eem_nodes = E_EM_BULB_HIGH 82 | Eem_hubs = E_EM_HUB_HIGH 83 | 84 | else: 85 | raise NameError 86 | 87 | Eem = number_os*Eem_os + number_nodes*Eem_nodes + number_hubs*Eem_hubs # units : MJ 88 | 89 | return Eem*1e6 # units = J 90 | 91 | def get_E_Operation(ARGS, scenario): 92 | "Output = energy in JOULES for ONE year" 93 | 94 | number_os, number_nodes, number_hubs = ARGS 95 | 96 | if (scenario == 'LOW'): 97 | Eop_os = POWER_SENSOR_MEAN*config.CONVERSION_YEAR_to_HOURS/1000*config.CONVERSION_kWh_to_MJ 98 | Eop_nodes = POWER_NODE_MEAN*config.CONVERSION_YEAR_to_HOURS/1000*config.CONVERSION_kWh_to_MJ 99 | Eop_hubs = (DUTY_CYCLE_SA*POWER_HUB_MEAN + (1-DUTY_CYCLE_SA)*POWER_HUB_MEAN)*config.CONVERSION_YEAR_to_HOURS/1000*config.CONVERSION_kWh_to_MJ 100 | 101 | elif(scenario == 'BENCHMARK'): 102 | Eop_os = POWER_SENSOR_MEAN*config.CONVERSION_YEAR_to_HOURS/1000*config.CONVERSION_kWh_to_MJ 103 | Eop_nodes = POWER_NODE_MEAN*config.CONVERSION_YEAR_to_HOURS/1000*config.CONVERSION_kWh_to_MJ 104 | Eop_hubs = (DUTY_CYCLE_SA*POWER_HUB_MEAN + (1-DUTY_CYCLE_SA)*POWER_HUB_MEAN)*config.CONVERSION_YEAR_to_HOURS/1000*config.CONVERSION_kWh_to_MJ 105 | 106 | elif(scenario == 'HIGH'): 107 | Eop_os = POWER_SENSOR_MEAN*config.CONVERSION_YEAR_to_HOURS/1000*config.CONVERSION_kWh_to_MJ 108 | Eop_nodes = POWER_NODE_MEAN*config.CONVERSION_YEAR_to_HOURS/1000*config.CONVERSION_kWh_to_MJ 109 | Eop_hubs = (DUTY_CYCLE_SA*POWER_HUB_MEAN + (1-DUTY_CYCLE_SA)*POWER_HUB_MEAN)*config.CONVERSION_YEAR_to_HOURS/1000*config.CONVERSION_kWh_to_MJ 110 | 111 | else: 112 | raise NameError 113 | 114 | Eop = number_os*Eop_os + number_nodes*Eop_nodes + number_hubs*Eop_hubs # units : MJ 115 | 116 | return Eop*1e6 # units = J 117 | 118 | def get_E_Maintenance(T_replacement, ARGS, scenario): 119 | 120 | number_os, number_nodes, number_hubs = ARGS 121 | 122 | if (scenario == 'LOW'): 123 | Em = number_nodes*0/T_replacement 124 | 125 | elif(scenario == 'BENCHMARK'): 126 | Em = number_nodes*0/T_replacement 127 | 128 | elif(scenario == 'HIGH'): 129 | Em = number_nodes*0/T_replacement 130 | 131 | else: 132 | raise NameError 133 | 134 | Em = Em*1 # energy "equivalent" over one year 135 | 136 | if (T_replacement < 0): Em = 0 137 | 138 | return Em*1e6 # units : J 139 | 140 | def get_E_EoL(scenario): 141 | 142 | if (scenario == 'LOW'): 143 | Er = 0 144 | 145 | elif(scenario == 'BENCHMARK'): 146 | Er = 0 147 | 148 | elif(scenario == 'HIGH'): 149 | Er = 0 150 | 151 | else: 152 | raise NameError 153 | 154 | return Er*1e6 # units : J -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # model -------------------------------------------------------------------------------- /SMTR_system.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @author: TSP 5 | """ 6 | 7 | import TSP_SMARTX_CONFIG_simple as config 8 | 9 | ############################################################################### 10 | # CONSTANTS # 11 | ############################################################################### 12 | 13 | #T_LIFETIME_SMTR = 15 # units : years 14 | POWER_SMTR_ACTIVE_LOW = 1.6 # units : W 15 | POWER_SMTR_ACTIVE_SPECS = 1.8 # units : W 16 | POWER_SMTR_ACTIVE_HIGH = 3 # units : W 17 | POWER_SMTR_SLEEP_SPECS = 1e6 # units : W 18 | DUTY_CYCLE_SA_USUAL_SMTR = 0.0 # 0 = always ACTIVE 19 | 20 | POWER_SMTR_DATA_COM = 0 #1.83 # units : W 21 | 22 | EMBODIED_ENERGY_SMTR_TYPICAL = 1511.31 # units : MJ 23 | EMBODIED_ENERGY_SMTR_LOW = 0.9*EMBODIED_ENERGY_SMTR_TYPICAL # units : MJ 24 | EMBODIED_ENERGY_SMTR_HIGH = 1.1*EMBODIED_ENERGY_SMTR_TYPICAL # units : MJ 25 | 26 | E_MAINT = 0 # units : MJ 27 | E_RECYCLING = 0 # units : MJ 28 | RAW_MAT_ENERGY_SMTR = 0#135 # units : MJ 29 | 30 | G_START_FSOLVE = 0.234 31 | 32 | ############################################################################### 33 | # FUNCTIONS # 34 | ############################################################################### 35 | 36 | 37 | def get_E_RawMaterials(scenario): 38 | 39 | if (scenario == 'LOW'): 40 | Erm = RAW_MAT_ENERGY_SMTR 41 | 42 | elif(scenario == 'BENCHMARK'): 43 | Erm = RAW_MAT_ENERGY_SMTR 44 | 45 | elif(scenario == 'HIGH'): 46 | Erm = RAW_MAT_ENERGY_SMTR 47 | 48 | else: 49 | raise NameError 50 | 51 | return Erm*1e6 # units : J 52 | 53 | def get_E_Embodied(scenario): 54 | 55 | if (scenario == 'LOW'): 56 | 57 | Eem = EMBODIED_ENERGY_SMTR_LOW 58 | 59 | elif(scenario == 'BENCHMARK'): 60 | 61 | Eem = EMBODIED_ENERGY_SMTR_TYPICAL 62 | 63 | elif(scenario == 'HIGH'): 64 | 65 | Eem = EMBODIED_ENERGY_SMTR_HIGH 66 | 67 | else: 68 | raise NameError 69 | 70 | return Eem*1e6# units : J 71 | 72 | def get_E_Operation(scenario): 73 | "Output = energy in JOULES for ONE year" 74 | 75 | if (scenario == 'LOW'): 76 | 77 | Eop = (DUTY_CYCLE_SA_USUAL_SMTR*POWER_SMTR_SLEEP_SPECS + (1-DUTY_CYCLE_SA_USUAL_SMTR)*(POWER_SMTR_ACTIVE_LOW + POWER_SMTR_DATA_COM))*config.CONVERSION_YEAR_to_SEC/1e6 # units : MJ 78 | 79 | elif(scenario == 'BENCHMARK'): 80 | 81 | Eop = (DUTY_CYCLE_SA_USUAL_SMTR*POWER_SMTR_SLEEP_SPECS + (1-DUTY_CYCLE_SA_USUAL_SMTR)*(POWER_SMTR_ACTIVE_SPECS + POWER_SMTR_DATA_COM))*config.CONVERSION_YEAR_to_SEC/1e6 # units : MJ 82 | 83 | elif(scenario == 'HIGH'): 84 | 85 | Eop = (DUTY_CYCLE_SA_USUAL_SMTR*POWER_SMTR_SLEEP_SPECS + (1-DUTY_CYCLE_SA_USUAL_SMTR)*(POWER_SMTR_ACTIVE_HIGH + POWER_SMTR_DATA_COM))*config.CONVERSION_YEAR_to_SEC/1e6 # units : MJ 86 | 87 | else: 88 | raise NameError 89 | 90 | return Eop*1e6 # units : J 91 | 92 | def get_E_Maintenance(T_replacement, ARGS, scenario): 93 | 94 | if (scenario == 'LOW'): 95 | Em = EMBODIED_ENERGY_SMTR_LOW/T_replacement 96 | 97 | elif(scenario == 'BENCHMARK'): 98 | Em = EMBODIED_ENERGY_SMTR_TYPICAL/T_replacement 99 | 100 | elif(scenario == 'HIGH'): 101 | Em = EMBODIED_ENERGY_SMTR_HIGH/T_replacement 102 | 103 | else: 104 | raise NameError 105 | 106 | Em = Em*1 # energy "equivalent" over one year 107 | 108 | if (T_replacement < 0): Em = 0 109 | 110 | return Em*1e6 # units : J 111 | 112 | def get_E_EoL(scenario): 113 | 114 | if (scenario == 'LOW'): 115 | Er = 0 116 | 117 | elif(scenario == 'BENCHMARK'): 118 | Er = 0 119 | 120 | elif(scenario == 'HIGH'): 121 | Er = 0 122 | 123 | else: 124 | raise NameError 125 | 126 | return Er*1e6 # units : J -------------------------------------------------------------------------------- /TSP_SMARTX_CONFIG_simple.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @author: TSP 5 | """ 6 | ############################################################################### 7 | # IMPORT # 8 | ############################################################################### 9 | 10 | import matplotlib.pyplot as plt 11 | import numpy as np 12 | import scipy.optimize as opt 13 | import sys 14 | from tqdm import tqdm 15 | 16 | import HUE_system as HUE 17 | import SMTR_system as SMTR 18 | import OFFICE_system as OFFICE 19 | ### import new system files here ... 20 | 21 | ############################################################################### 22 | # CONSTANTS # 23 | ############################################################################### 24 | 25 | ### CONVERSION ### 26 | 27 | CONVERSION_Wh_to_J = 3.6e3 # units : J/Wh 28 | CONVERSION_kWh_to_J = CONVERSION_Wh_to_J*1e3 # units : J/kWh 29 | CONVERSION_kWh_to_MJ = CONVERSION_Wh_to_J/1e3 # units : MJ/kWh 30 | 31 | CONVERSION_DAY_to_SEC = 24*60*60 32 | 33 | CONVERSION_YEAR_to_DAYS = 365.25 # units : days 34 | CONVERSION_YEAR_to_HOURS = 24*CONVERSION_YEAR_to_DAYS # units : hours 35 | CONVERSION_YEAR_to_SEC = CONVERSION_YEAR_to_DAYS*CONVERSION_DAY_to_SEC # units : seconds 36 | 37 | ### CONSTANTS 38 | ELEC_TO_PRIMARY_ENERGY = 3 # units : / 39 | 40 | T_PB_INFINITY = 1e3 # units : years 41 | 42 | ### PARAMETERS 43 | TIME_HORIZON = 50 # units : years 44 | 45 | ############################################################################### 46 | # FUNCTIONS # 47 | ############################################################################### 48 | 49 | class SmartSystem: 50 | 51 | def __init__(self, system_ID, baseline_power, alpha0, PTT, beta, lifetime_system, color, args): 52 | self.system_ID = system_ID 53 | self.baseline_power = baseline_power 54 | 55 | self.alpha0 = alpha0 56 | self.PTT = PTT 57 | 58 | self.beta = beta 59 | self.lifetime_system = lifetime_system 60 | 61 | self.color_all = color 62 | self.args = args 63 | 64 | self.baseline_power_system = -1 65 | self.setup = 'empty' 66 | 67 | def setBaselinePowerSystem(self, bps): 68 | self.baseline_power_system = bps 69 | 70 | def setSetupNameDetails(self, name_str): 71 | self.setup = name_str 72 | 73 | 74 | ############################################################################### 75 | 76 | def plotSpecificAlpha(System_sel): 77 | "PLOT TPB for specific cases of alpha0" 78 | 79 | number_of_coeff = len(System_sel.alpha0) 80 | 81 | sys_coeff_ID = [] 82 | 83 | for current_alpha0 in range(number_of_coeff): 84 | 85 | sys_coeff_ID.append(System_sel.system_ID + '\n\u03B1='+str(System_sel.alpha0[current_alpha0]*100) + '%') 86 | 87 | t_pb_all = [] 88 | uncert_all = [] 89 | 90 | for current_alpha0 in range(number_of_coeff): 91 | 92 | t_pb, uncert, _ , _, _ = get_TPB(System_sel, System_sel.alpha0[current_alpha0], True) 93 | 94 | t_pb_all.append(t_pb) 95 | uncert_all.append([t_pb - uncert[0], uncert[1] - t_pb]) 96 | 97 | print("*** $\u03B1_0$ = {}% | \u03B2 = {} hours/day \n<-> {} hours less utilization needed \n<-> {} W power saved\n".format(System_sel.alpha0[current_alpha0]*100, round(System_sel.beta*24, 1), round(System_sel.alpha0[current_alpha0]*System_sel.beta*24, 1), round(System_sel.alpha0[current_alpha0]*System_sel.beta*System_sel.baseline_power_system, 1))) 98 | 99 | fig, ax = plt.subplots(1) 100 | 101 | plt.bar(np.asarray(sys_coeff_ID), np.asarray(t_pb_all), color=System_sel.color_all) 102 | plt.errorbar(np.asarray(sys_coeff_ID), np.asarray(t_pb_all), yerr = np.transpose(np.asarray(uncert_all)), label='Uncertainty', fmt = 'none', capsize = 6, ecolor = 'black', elinewidth = 1, capthick = 2) #xerr = lumin_techno, yerr = [10, 10, 10] 103 | 104 | #plt.fill_between(np.asarray(sys_coeff_ID), 0, System_sel.lifetime_system, alpha=0.1, edgecolor='#1B2ACC', facecolor='magenta',linewidth=1, linestyle='dashdot', antialiased=True, label='System\'s lifetime') 105 | plt.hlines(System_sel.lifetime_system, sys_coeff_ID[0], sys_coeff_ID[-1], colors='magenta', linestyles='dashed', label='System\'s lifetime (= {} years)'.format(System_sel.lifetime_system), alpha=0.2) 106 | 107 | 108 | plt.yscale('log') 109 | plt.ylim([1e-3, TIME_HORIZON]) 110 | ax.set_axisbelow(True) 111 | plt.grid(color='lightgray', linestyle='dashed') 112 | 113 | plt.title('Payback time - Project : {}\nSetup = {}\n\u03B2 = {}\n'.format(System_sel.system_ID, System_sel.setup, round(System_sel.beta, 2))) 114 | plt.ylabel('Payback Time [years]') 115 | plt.xlabel('System ID') 116 | 117 | plt.grid(alpha=0.2) 118 | plt.legend() 119 | 120 | ############################################################################### 121 | 122 | def plotBulbsImpactHUE(System_sel): 123 | "PLOT the evolution of TPB depending on the number of bulbs in the system" 124 | 125 | memory_bps = System_sel.baseline_power_system 126 | memory_args = System_sel.args 127 | 128 | bulbs_range = [1, 51] #maximum 50 nodes connected to a HUE hub 129 | bulbs = range(bulbs_range[0], bulbs_range[1]) 130 | 131 | t_pb_usual = [] 132 | t_pb_up = [] 133 | t_pb_dn = [] 134 | 135 | coeff_index = 1 136 | 137 | for bulb in bulbs: 138 | 139 | System_sel.setBaselinePowerSystem(System_sel.baseline_power*bulb) 140 | System_sel.args = [System_sel.args[0], bulb, System_sel.args[2]] 141 | 142 | t_pb, uncert, _ , _, _ = get_TPB(System_sel, System_sel.alpha0[coeff_index], False) 143 | 144 | t_pb_usual.append(t_pb) 145 | t_pb_up.append(uncert[1]) 146 | t_pb_dn.append(uncert[0]) 147 | 148 | plt.figure() 149 | 150 | plt.plot(bulbs, t_pb_usual, label='Typical') 151 | plt.plot(bulbs, t_pb_up, 'r', alpha=0.5, label='Upper boundary') 152 | plt.plot(bulbs, t_pb_dn, 'g', alpha=0.5, label='Lower boundary') 153 | 154 | plt.hlines(System_sel.lifetime_system, bulbs[0], bulbs[-1], colors='magenta', linestyles='dashed', label='System\'s lifetime (= {} years)'.format(System_sel.lifetime_system), alpha=0.2) 155 | 156 | plt.yscale('log') 157 | plt.ylim([0, TIME_HORIZON]) 158 | 159 | plt.title('Evolution of the payback time depending on the number of smart bulbs per hub\nSystem = {} - $\u03B1_0$ = {} - \u03B2 = {}\n'.format(System_sel.system_ID, System_sel.alpha0[coeff_index], round(System_sel.beta, 2))) 160 | plt.ylabel('T_PB [years]') 161 | plt.xlabel('Number of smart bulbs [/]') 162 | plt.xlim([0, bulbs_range[1]]) 163 | 164 | plt.grid(alpha=0.2) 165 | plt.legend() 166 | 167 | # restore default parameters 168 | System_sel.setBaselinePowerSystem(memory_bps) 169 | System_sel.args = memory_args 170 | 171 | ############################################################################### 172 | 173 | def plotTPB_AlphaRange(System_sel): 174 | "PLOT TPB for a range of alpha0 \ 175 | PLOT potential savingsfor a range of alpha0 \ 176 | CHECK if fsolve did its job properly" 177 | 178 | ### PLOT TPB for a range of alpha0 179 | 180 | alpha0_range = [0, 1] 181 | alpha0 = np.arange(alpha0_range[0], alpha0_range[1], 0.001) #0.0001 182 | 183 | t_pb_usual = [] 184 | t_pb_up = [] 185 | t_pb_dn = [] 186 | 187 | t_pb_solved_all = [] 188 | 189 | savings_b = [] 190 | savings_w = [] 191 | Esmart_atLT = [] 192 | 193 | G_all = [] 194 | 195 | for current_alpha0 in tqdm(range(len(alpha0))): 196 | 197 | t_pb, uncert, t_pb_solved, savings, G = get_TPB(System_sel, alpha0[current_alpha0], False) 198 | 199 | t_pb_usual.append(t_pb) 200 | t_pb_up.append(uncert[1]) 201 | t_pb_dn.append(uncert[0]) 202 | 203 | t_pb_solved_all.append(t_pb_solved) 204 | 205 | savings_b.append(savings[0]) 206 | savings_w.append(savings[1]) 207 | Esmart_atLT.append(savings[2]) 208 | 209 | G_all.append(G) 210 | 211 | plt.figure() 212 | 213 | plt.plot(alpha0*100, t_pb_usual, label='Typical') 214 | plt.plot(alpha0*100, t_pb_up, 'r', alpha=0.5, label='Upper boundary') 215 | plt.plot(alpha0*100, t_pb_dn, 'g', alpha=0.5, label='Lower boundary') 216 | 217 | plt.plot(alpha0*100, t_pb_solved_all, '--', color='blue', alpha=0.4, label='Influence of a varying \u03B1 \non the typical scenario') 218 | 219 | plt.hlines(System_sel.lifetime_system, alpha0[0]*100, alpha0[-1]*100, colors='magenta', linestyles='dashed', label='System\'s lifetime (= {} years)'.format(System_sel.lifetime_system), alpha=0.2) 220 | 221 | alpha0_wsavings = alpha0[np.where(np.asarray(savings_w)>=0)[0][0]]*100 if len(np.where(np.asarray(savings_w)>=0)[0]) != 0 else alpha0[-1]*100 222 | plt.vlines(alpha0_wsavings, 0, TIME_HORIZON, colors='black', linestyles='dashed', label='W-savings boundary', alpha=0.2) 223 | 224 | plt.fill_between(alpha0*100, t_pb_dn, t_pb_up, alpha=0.1, facecolor='grey', antialiased=True) 225 | 226 | plt.yscale('log') 227 | plt.ylim([0, TIME_HORIZON]) 228 | plt.xlim([0, alpha0_range[1]*100]) 229 | 230 | plt.title('Evolution of the payback time depending on \u03B1\nSystem = {}\n\u03B2 = {} | Setup = {}\nPTT = {}'.format(System_sel.system_ID, round(System_sel.beta, 2), System_sel.setup, System_sel.PTT)) 231 | plt.ylabel('$T_{PB}$ [years]') 232 | plt.xlabel('$\u03B1_0$ [%]') 233 | 234 | plt.grid(alpha=0.2) 235 | plt.legend() 236 | 237 | ### PLOT potential savings depending on alpha0 238 | 239 | fig, ax1 = plt.subplots() 240 | 241 | ax1.plot(alpha0*100, savings_b, alpha=0.5, label='Best case savings (Benchmarck, \u03B1 constant)') 242 | ax1.plot(alpha0*100, savings_w, '--', color='blue', alpha=0.5, label='Worst case savings (Benchmarck, \u03B1 varying)') 243 | ax1.hlines(0, alpha0[0]*100, alpha0[-1]*100, colors='olive', linestyles='dashed', label='No savings', alpha=0.4) 244 | 245 | ax1.fill_between(alpha0*100, savings_w, savings_b, alpha=0.1, facecolor='grey', antialiased=True) 246 | 247 | ax1.vlines(alpha0_wsavings, 0, max(savings_b), colors='black', linestyles='dashed', label='W-savings boundary', alpha=0.2) 248 | 249 | #plt.yscale('log') 250 | ax1.set_ylim([min(savings_w), max(savings_b)]) 251 | 252 | ax1.set_title('Evolution of potential savings at the end of system\'s lifetime depending on \u03B1\nSystem = {}\n\u03B2 = {}\nSetup = {}'.format(System_sel.system_ID, round(System_sel.beta, 2), System_sel.setup)) 253 | ax1.set_ylabel('Savings [%]') 254 | ax1.set_xlabel('$\u03B1_0$ [%]') 255 | 256 | ax2 = ax1.twinx() 257 | y1, y2 = ax1.get_ylim() 258 | ax2.set_ylim(y1/100*Esmart_atLT[0]/1e6, y2/100*Esmart_atLT[0]/1e6) 259 | ax2.figure.canvas.draw() 260 | ax2.set_ylabel('Savings [MJ]') 261 | 262 | ax1.grid(alpha=0.2) 263 | ax1.legend() 264 | 265 | # plt.figure() 266 | # plt.plot(alpha0*100, np.asarray(G_all)/1e6, 'x') 267 | # plt.plot(alpha0*100, np.asarray(savings_w)/100*Esmart_atLT[0]/1e6, '--', color='blue', alpha=0.5, label='Worst case savings (Benchmarck, \u03B1 varying. (\u03C4={} years))'.format(System_sel.PTT[1])) 268 | 269 | ### Check FSOLVE results on the range of alpha0 270 | if (1): 271 | diff_solved = np.diff(t_pb_solved_all) 272 | monotone_decr = max(diff_solved) > 0.0 273 | 274 | if (monotone_decr): 275 | raise ValueError("[CRITICAL ERROR] : please enter another value for G_START_FSOLVE ... \n") 276 | 277 | # plt.figure() 278 | # plt.title('Influence of a varying \u03B1 \non the payback time, typical scenario') 279 | # plt.ylabel('T_PB [years]') 280 | # plt.xlabel('$\u03B1_0$ [%]') 281 | # plt.plot(alpha0*100, t_pb_solved_all, alpha=0.6, color='grey') 282 | # plt.yscale('log') 283 | #plt.ylim([0, config.TIME_HORIZON]) 284 | 285 | ############################################################################### 286 | 287 | def TPB(Erm, Eem, Er, P_saved, Pm, Pop): 288 | "This function returns the payback time. \ 289 | - units output = years \ 290 | - Exxx units = Joules whereas Pxxx units = Watts" 291 | 292 | num = Erm + Eem + Er 293 | denom = ELEC_TO_PRIMARY_ENERGY*CONVERSION_YEAR_to_SEC*P_saved - ELEC_TO_PRIMARY_ENERGY*CONVERSION_YEAR_to_SEC*Pop - CONVERSION_YEAR_to_SEC*Pm 294 | 295 | if (denom <= 0): 296 | t_pb = T_PB_INFINITY 297 | 298 | else: 299 | t_pb = num/denom 300 | 301 | return t_pb 302 | 303 | ############################################################################### 304 | 305 | def G(t, Erm, Eem, Er, beta, alpha0, baseline_power_system, Pm, Pop, PTT): 306 | "This function returns the NET gains a time t. \ 307 | - units output = Joules, Primary Energy \ 308 | - t and tau have to be given in the same units \ 309 | - Exxx units = Joules whereas Pxxx units = Watts " 310 | 311 | #g = ELEC_TO_PRIMARY_ENERGY*CONVERSION_YEAR_to_SEC*baseline_power_system*beta*alpha0*(phi*t + tau*theta*(1-np.exp(-t/tau))) - ELEC_TO_PRIMARY_ENERGY*CONVERSION_YEAR_to_SEC*Pop*t - CONVERSION_YEAR_to_SEC*Pm*t - Eem - Erm - Er 312 | 313 | g = E_saved_f(PTT, t, alpha0, beta, baseline_power_system) - E_smart(Erm, Eem, Er, Pop, Pm, t) 314 | 315 | return g 316 | 317 | ############################################################################### 318 | 319 | def E_saved_f(PTT, time, alpha0, beta, baseline_power_system): 320 | "This function returns ONLY the energy saved by the introduction of the smart layer. \ 321 | - units output = Joules, Primary Energy" 322 | 323 | if (type(time) == int): 324 | time = [time] 325 | 326 | time = np.asarray(time) 327 | 328 | E_s = [] 329 | PTT_array = np.asarray(PTT) 330 | 331 | limit = np.cumsum(PTT_array[:,1][0:-1]) 332 | limit = np.append(0, limit) 333 | limit = np.append(limit, TIME_HORIZON) 334 | 335 | weight = [] 336 | 337 | for t in time: 338 | for ind in range(len(limit)-1): 339 | if ((t - limit[ind]) >= 0) and ((t - limit[ind+1]) <= 0): 340 | weight.append((t - limit[ind])) 341 | elif ((t - limit[ind]) >= 0) and ((t - limit[ind+1]) >= 0): 342 | weight.append(1*abs(PTT_array[ind,1])) 343 | elif ((t - limit[ind]) <= 0) and ((t - limit[ind+1]) <= 0): 344 | weight.append(0) 345 | 346 | coef = weight*PTT_array[:, 0] 347 | weight = [] 348 | 349 | E_s.append(np.sum(ELEC_TO_PRIMARY_ENERGY*CONVERSION_YEAR_to_SEC*beta*baseline_power_system*alpha0*coef)) 350 | 351 | if (len(time)==1): 352 | E_s = E_s[0] 353 | 354 | return np.asarray(E_s) 355 | 356 | ############################################################################### 357 | 358 | def E_smart(Erm, Eem, Er, Pop, Pm, t): 359 | "This function returns ONLY the energy of the smart layer at a time t. \ 360 | - units input = t [years] \ 361 | - units output = Joules, Primary Energy" 362 | 363 | E_smart = (Erm + Er + Eem) + (ELEC_TO_PRIMARY_ENERGY*Pop + Pm)*CONVERSION_YEAR_to_SEC*t 364 | 365 | return E_smart 366 | 367 | ############################################################################### 368 | 369 | def alpha_t(time, alpha0, PTT): 370 | "This function returns the value of alpha through time. \ 371 | - units output = / " 372 | # Time and tau have to be given with the same units 373 | 374 | time = np.asarray(time) 375 | 376 | alpha = [] 377 | PTT_array = np.asarray(PTT) 378 | 379 | limit = np.cumsum(PTT_array[:,1][0:-1]) 380 | limit = np.append(limit, TIME_HORIZON) 381 | 382 | for t in time: 383 | if (len(PTT) == 1): 384 | alpha.append(alpha0*PTT_array[0, 0]) 385 | elif (t < limit[0]): 386 | alpha.append(alpha0*PTT_array[0, 0]) 387 | elif(t > limit[0]): 388 | alpha.append(alpha0*PTT_array[np.where(t > limit)[-1][-1]+1, 0]) 389 | 390 | return np.asarray(alpha) 391 | 392 | ############################################################################### 393 | 394 | def plot_EC(axes, title, days, E_em, E_op, E_saved, t_pb, lifetime_system, savings, alpha0, PTT, beta, baseline_power_system): 395 | "Plot energy curves for given parameters" 396 | 397 | axes.plot(days, np.asarray(E_em)/1e6, 'r', alpha=0.2, linewidth= 1, label='Embodied energy') 398 | axes.plot(days, np.asarray(E_op)/1e6, 'b', alpha=0.2, linewidth= 1, label='Use-phase energy') 399 | axes.plot(days, np.asarray(E_op + E_em)/1e6, 'k', linewidth= 1, label='Energy for the smart layer') 400 | axes.plot(days, np.asarray(E_saved)/1e6, 'g-', linewidth= 1, label='Energy saved thanks to the smartness\n\u03B1 constant') 401 | 402 | axes.vlines(t_pb, 0, max(E_saved)/1e6, colors='olive', linestyles='dashed', label='T_PB', alpha=0.4) 403 | axes.vlines(lifetime_system, 0, max(E_saved)/1e6, colors='magenta', linestyles='dashed', label='T_lifetime (= {} years)\nb-savings = {}% | w-savings = {}%)'.format(lifetime_system, savings[0], savings[1]), alpha=0.4) 404 | 405 | axes.plot(days, E_saved_f(PTT, days, alpha0, beta, baseline_power_system)/1e6, label='Energy saved thanks to the smartness\n\u03B1 changes with time') 406 | 407 | axes.set_ylim([0, max(E_saved)/1e6]) 408 | axes.set_ylabel('Energy [MJ]') 409 | 410 | Esmart_at_lifetime = savings[2]/1e6 411 | ax2 = axes.twinx() 412 | y1, y2 = axes.get_ylim() 413 | ax2.set_ylim(y1/Esmart_at_lifetime*100, y2/Esmart_at_lifetime*100) 414 | ax2.figure.canvas.draw() 415 | ax2.set_ylabel('Relative share w.r.t. $E_{smart}$ at system\'s lifetime [%]') 416 | 417 | axes.set_title(title + ' - T_PB = {} days = {} years'.format(round(t_pb*CONVERSION_YEAR_to_DAYS), round(t_pb, 2))) 418 | axes.grid(alpha=0.2) 419 | 420 | if (t_pb > lifetime_system): axes.text(0, 0, 'PAYBACK TIME IS GREATER THAN SYSTEM LIFETIME !', fontsize=12, bbox=dict(facecolor='red', alpha=0.7)) 421 | 422 | ############################################################################### 423 | 424 | def get_TPB(System_sel, alpha0, plot_energy_curves): 425 | "This is the main function. It returns the payback time for the given parameters. \ 426 | - units output = [years, years, years, %]. " 427 | 428 | ### Params 429 | system_ID = System_sel.system_ID 430 | PTT = System_sel.PTT 431 | beta = System_sel.beta 432 | baseline_power_system = System_sel.baseline_power_system 433 | lifetime_system = System_sel.lifetime_system 434 | ARGS = System_sel.args 435 | 436 | P_saved = baseline_power_system*alpha0*beta # W = J/s 437 | 438 | #TIME_HORIZON = lifetime_system*1.2 439 | 440 | if (system_ID == 'PHILIPS-HUE-LED' or system_ID == 'PHILIPS-HUE-CFL' or system_ID == 'PHILIPS-HUE-INC'): 441 | 442 | G_start_fsolve = HUE.G_START_FSOLVE 443 | 444 | Erm = HUE.get_E_RawMaterials('BENCHMARK') 445 | Erm_DN = HUE.get_E_RawMaterials('LOW') 446 | Erm_UP = HUE.get_E_RawMaterials('HIGH') 447 | 448 | Eem = HUE.get_E_Embodied(ARGS, 'BENCHMARK') 449 | Eem_DN = HUE.get_E_Embodied(ARGS, 'LOW') 450 | Eem_UP = HUE.get_E_Embodied(ARGS, 'HIGH') 451 | 452 | Pop = HUE.get_E_Operation(ARGS, 'BENCHMARK')/CONVERSION_YEAR_to_SEC 453 | Pop_DN = HUE.get_E_Operation(ARGS, 'LOW')/CONVERSION_YEAR_to_SEC 454 | Pop_UP = HUE.get_E_Operation(ARGS, 'HIGH')/CONVERSION_YEAR_to_SEC 455 | 456 | if (system_ID == 'PHILIPS-HUE-LED'): 457 | T_replacement = HUE.LIFETIME_LED/(beta*CONVERSION_YEAR_to_HOURS*(1-alpha0)) 458 | elif (system_ID == 'PHILIPS-HUE-CFL'): 459 | T_replacement = HUE.LIFETIME_CFL/(beta*CONVERSION_YEAR_to_HOURS*(1-alpha0)) 460 | elif (system_ID == 'PHILIPS-HUE-INC'): 461 | T_replacement = HUE.LIFETIME_INC/(beta*CONVERSION_YEAR_to_HOURS*(1-alpha0)) 462 | else: 463 | raise NameError 464 | 465 | T_replacement = -1 466 | 467 | Pm = HUE.get_E_Maintenance(T_replacement, ARGS, 'BENCHMARK')/CONVERSION_YEAR_to_SEC 468 | Pm_DN = HUE.get_E_Maintenance(T_replacement, ARGS, 'LOW')/CONVERSION_YEAR_to_SEC 469 | Pm_UP = HUE.get_E_Maintenance(T_replacement, ARGS, 'HIGH')/CONVERSION_YEAR_to_SEC 470 | 471 | Er = HUE.get_E_EoL('BENCHMARK') 472 | Er_DN = HUE.get_E_EoL('LOW') 473 | Er_UP = HUE.get_E_EoL('HIGH') 474 | 475 | 476 | elif(system_ID == 'SMART-METER'): 477 | 478 | if (ARGS != None): raise TypeError 479 | 480 | G_start_fsolve = SMTR.G_START_FSOLVE 481 | 482 | Erm = SMTR.get_E_RawMaterials('BENCHMARK') 483 | Erm_DN = SMTR.get_E_RawMaterials('LOW') 484 | Erm_UP = SMTR.get_E_RawMaterials('HIGH') 485 | 486 | Eem = SMTR.get_E_Embodied('BENCHMARK') 487 | Eem_DN = SMTR.get_E_Embodied('LOW') 488 | Eem_UP = SMTR.get_E_Embodied('HIGH') 489 | 490 | Pop = SMTR.get_E_Operation('BENCHMARK')/CONVERSION_YEAR_to_SEC 491 | Pop_DN = SMTR.get_E_Operation('LOW')/CONVERSION_YEAR_to_SEC 492 | Pop_UP = SMTR.get_E_Operation('HIGH')/CONVERSION_YEAR_to_SEC 493 | 494 | T_replacement = 1e6 # years 495 | 496 | Pm = SMTR.get_E_Maintenance(T_replacement, ARGS, 'BENCHMARK')/CONVERSION_YEAR_to_SEC 497 | Pm_DN = SMTR.get_E_Maintenance(T_replacement, ARGS, 'LOW')/CONVERSION_YEAR_to_SEC 498 | Pm_UP = SMTR.get_E_Maintenance(T_replacement, ARGS, 'HIGH')/CONVERSION_YEAR_to_SEC 499 | 500 | Er = SMTR.get_E_EoL('BENCHMARK') 501 | Er_DN = SMTR.get_E_EoL('LOW') 502 | Er_UP = SMTR.get_E_EoL('HIGH') 503 | 504 | elif(system_ID == 'OFFICE-LIGHTNING'): 505 | 506 | G_start_fsolve = OFFICE.G_START_FSOLVE 507 | 508 | Erm = OFFICE.get_E_RawMaterials('BENCHMARK') 509 | Erm_DN = OFFICE.get_E_RawMaterials('LOW') 510 | Erm_UP = OFFICE.get_E_RawMaterials('HIGH') 511 | 512 | Eem = OFFICE.get_E_Embodied(ARGS, 'BENCHMARK') 513 | Eem_DN = OFFICE.get_E_Embodied(ARGS, 'LOW') 514 | Eem_UP = OFFICE.get_E_Embodied(ARGS, 'HIGH') 515 | 516 | Pop = OFFICE.get_E_Operation(ARGS, 'BENCHMARK')/CONVERSION_YEAR_to_SEC 517 | Pop_DN = OFFICE.get_E_Operation(ARGS, 'LOW')/CONVERSION_YEAR_to_SEC 518 | Pop_UP = OFFICE.get_E_Operation(ARGS, 'HIGH')/CONVERSION_YEAR_to_SEC 519 | 520 | T_replacement = OFFICE.LIFETIME_LIGHT/(beta*CONVERSION_YEAR_to_HOURS*(1-alpha0)) 521 | 522 | Pm = OFFICE.get_E_Maintenance(T_replacement, ARGS, 'BENCHMARK')/CONVERSION_YEAR_to_SEC 523 | Pm_DN = OFFICE.get_E_Maintenance(T_replacement, ARGS, 'LOW')/CONVERSION_YEAR_to_SEC 524 | Pm_UP = OFFICE.get_E_Maintenance(T_replacement, ARGS, 'HIGH')/CONVERSION_YEAR_to_SEC 525 | 526 | Er = OFFICE.get_E_EoL('BENCHMARK') 527 | Er_DN = OFFICE.get_E_EoL('LOW') 528 | Er_UP = OFFICE.get_E_EoL('HIGH') 529 | 530 | elif(system_ID == 'other'): 531 | 532 | # other systems can be added here 533 | print('\n Please add another system CONFIG or select another existing system CONFIG ! \n') 534 | sys.exit(2) 535 | 536 | else: 537 | raise NameError 538 | 539 | t_pb = TPB(Erm, Eem, Er, P_saved, Pm, Pop) # units : years 540 | 541 | # uncertainty 542 | uncert = [] 543 | 544 | t_pb_DN = TPB(Erm_DN, Eem_DN, Er_DN, P_saved, Pm_DN, Pop_DN) 545 | 546 | t_pb_UP = TPB(Erm_UP, Eem_UP, Er_UP, P_saved, Pm_UP, Pop_UP) 547 | 548 | uncert.append(t_pb_DN) 549 | uncert.append(t_pb_UP) 550 | 551 | time_gains = np.linspace(0, TIME_HORIZON, 1000) 552 | gains_tau = G(time_gains, Erm, Eem, Er, beta, alpha0, baseline_power_system, Pm, Pop, PTT) 553 | 554 | t_pb_solved = opt.fsolve(G, G_start_fsolve, args=(Erm, Eem, Er, beta, alpha0, baseline_power_system, Pm, Pop, PTT)) 555 | t_pb_solved = T_PB_INFINITY if (max(gains_tau) < 0) else t_pb_solved[0] 556 | 557 | number_of_days = int(CONVERSION_YEAR_to_DAYS*TIME_HORIZON) 558 | # days = np.asarray(range(0, number_of_days))/CONVERSION_YEAR_to_DAYS 559 | days = np.linspace(0, TIME_HORIZON, number_of_days) 560 | 561 | def list_E(Erm, Eem, Er, Pm, Pop): 562 | 563 | E_em = np.linspace(Eem + Erm + Er, Eem + Erm + Er + Pm*CONVERSION_YEAR_to_SEC*TIME_HORIZON, number_of_days) 564 | E_op = np.linspace(0, ELEC_TO_PRIMARY_ENERGY*Pop*CONVERSION_YEAR_to_SEC*TIME_HORIZON, number_of_days) 565 | E_saved = np.linspace(0, ELEC_TO_PRIMARY_ENERGY*P_saved*CONVERSION_YEAR_to_SEC*TIME_HORIZON, number_of_days) 566 | 567 | E_smart_atLT = E_smart(Erm, Eem, Er, Pop, Pm, lifetime_system) 568 | 569 | bsavings = np.around(G(lifetime_system, Erm, Eem, Er, beta, alpha0, baseline_power_system, Pm, Pop, [[1, -1]])/E_smart_atLT*100, 2) 570 | wsavings = np.around(G(lifetime_system, Erm, Eem, Er, beta, alpha0, baseline_power_system, Pm, Pop, PTT)/E_smart_atLT*100, 2) 571 | 572 | return E_em, E_op, E_saved, [bsavings, wsavings, E_smart_atLT] 573 | 574 | E_em, E_op, E_saved, savings = list_E(Erm, Eem, Er, Pm, Pop) 575 | E_em_DN, E_op_DN, E_saved_DN, savings_DN = list_E(Erm_DN, Eem_DN, Er_DN, Pm_DN, Pop_DN) 576 | E_em_UP, E_op_UP, E_saved_UP, savings_UP = list_E(Erm_UP, Eem_UP, Er_UP, Pm_UP, Pop_UP) 577 | 578 | if (plot_energy_curves): 579 | 580 | ########### Energy curves 581 | if(0): 582 | fig, (ax1, ax2, ax3) = plt.subplots(3, 1, sharex=True) 583 | fig.suptitle('Energy curves for {}\n$\u03B1_0$ = {}% - \u03B2 = {}\n'.format(system_ID, alpha0*100, round(beta, 2))) 584 | 585 | plot_EC(ax1, 'Lower boundary', days, E_em_DN, E_op_DN, E_saved_DN, t_pb_DN, lifetime_system, savings_DN, alpha0, PTT, beta, baseline_power_system) 586 | ax1.set_xlim([0, TIME_HORIZON]) 587 | 588 | #ax1.legend(loc='center left', bbox_to_anchor=(1, 0.5)) 589 | 590 | plot_EC(ax2, 'Typical', days, E_em, E_op, E_saved, t_pb, lifetime_system, savings, alpha0, PTT, beta, baseline_power_system) 591 | #if (system_ID == 'PHILIPS-HUE-LED'): plt.vlines(T_life_bulb*CONVERSION_YEAR_to_DAYS, 0, max(E_saved)/1e6, colors='orange', linestyles='dashed', label='T_life_bulbFF (= {} years)'.format(round(T_life_bulb, 2)), alpha=0.4) 592 | 593 | plot_EC(ax3, 'Upper boundary', days, E_em_UP, E_op_UP, E_saved_UP, t_pb_UP, lifetime_system, savings_UP, alpha0, PTT, beta, baseline_power_system) 594 | ax3.set_xlabel('Time [years]') 595 | 596 | ########### plot energy curves only for typical scenario 597 | fig, ax1 = plt.subplots() 598 | title = 'Energy curves for {}\n$\u03B1_0$ = {}% - \u03B2 = {}\nTypical'.format(system_ID, alpha0*100, round(beta, 2)) 599 | plot_EC(ax1, title, days, E_em, E_op, E_saved, t_pb, lifetime_system, savings, alpha0, PTT, beta, baseline_power_system) 600 | 601 | ax1.set_xlabel('Time [years]') 602 | #ax2 = ax1.twinx() 603 | #ax2.set_ylabel('Share of the total smart layer energy (over lifetime) [%]') 604 | ax1.legend() 605 | 606 | 607 | ########### Evolution of G(t) and alpha(t) 608 | fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True) 609 | fig.suptitle('Influence of a varying \u03B1\n$\u03B1_0$ = {}%\n'.format(alpha0*100)) #fontsize=16 610 | 611 | # G(t) 612 | ax1.plot(time_gains, gains_tau/1e6, label='Net gains') 613 | if (system_ID == 'PHILIPS-HUE-LED' and T_replacement > 0): ax1.vlines(T_replacement, 0, max(gains_tau)/1e6, colors='black', linestyles='dashed', label='T_replacement (= {} years)'.format(round(T_replacement, 2)), alpha=0.4) 614 | ax1.vlines(lifetime_system, min(gains_tau)/1e6, max(gains_tau)/1e6, colors='magenta', linestyles='dashed', label='T_lifetime (= {} years)'.format(lifetime_system), alpha=0.4) 615 | 616 | ax1.set_xlim([0, TIME_HORIZON]) 617 | ax1.set_ylabel('Gains [MJ]') 618 | ax1.set_title('Evolution of G(t) for the typical scenario') 619 | 620 | ax1.grid(alpha=0.2) 621 | ax1.legend() 622 | 623 | # alpha(t) 624 | ax2.plot(days, alpha_t(days, alpha0, PTT), label='Discontinuous $\u03B1$') 625 | ax2.hlines(alpha0, min(time_gains), max(time_gains), colors='grey', linestyles='dashed', label='$\u03B1_0$', alpha=0.5) 626 | 627 | ax2.set_ylabel('$\u03B1$ [/]') 628 | ax2.set_xlabel('Time [years]') 629 | ax2.set_title('Evolution of $\u03B1(t)$') 630 | 631 | ax2.grid(alpha=0.2) 632 | ax2.legend() 633 | 634 | return t_pb, uncert, t_pb_solved, savings, G(lifetime_system, Erm, Eem, Er, beta, alpha0, baseline_power_system, Pm, Pop, PTT) 635 | 636 | # end of script -------------------------------------------------------------------------------- /TSP_SMARTX_MAIN.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @author: TSP 5 | """ 6 | ############################################################################### 7 | 8 | import sys 9 | 10 | #import TSP_SMARTX_CONFIG as config 11 | import TSP_SMARTX_CONFIG_simple as config 12 | 13 | ############################################################################### 14 | 15 | ### Systems definition 16 | 17 | ## PARAMS = (system_ID, 18 | # baseline_power, 19 | # specific alpha_0, 20 | # PTT, 21 | # beta, 22 | # lifetime_system, 23 | # color, 24 | # args) 25 | 26 | # PHILIPS HUE 27 | 28 | HUE_system_LED = config.SmartSystem('PHILIPS-HUE-LED', \ 29 | 9, \ 30 | [0.17, 0.70, 0.35],\ 31 | [[1, -1]], \ 32 | (1000/365.25)/24, \ 33 | 5, \ 34 | ['peachpuff'], \ 35 | [2, 8, 1]) 36 | 37 | # SMART METER 38 | SMTR_system = config.SmartSystem('SMART-METER', \ 39 | 524, \ 40 | [0.03, 0.08, 0.15], \ 41 | [[1, 0.5], [0, -1]], \ 42 | 24/24, \ 43 | 15, \ 44 | ['peachpuff'], \ 45 | None) 46 | 47 | 48 | # OFFICE LIGHTNING 49 | OFFICE_LIGHT_system = config.SmartSystem('OFFICE-LIGHTNING', \ 50 | 100, \ 51 | [0.2, 0.35, 0.5], \ 52 | [[1, -1]], \ 53 | (2500*0.6/365.25)/24, \ 54 | 15, \ 55 | ['peachpuff'], \ 56 | [1, 4, 0]) 57 | 58 | ############################################################################### 59 | 60 | # SYSTEM SELECTION 61 | System_sel = OFFICE_LIGHT_system 62 | 63 | ############################################################################### 64 | 65 | ### Defines the baseline power of the whole system considered 66 | 67 | if (System_sel.system_ID == 'PHILIPS-HUE-LED' or System_sel.system_ID == 'PHILIPS-HUE-CFL' or System_sel.system_ID == 'PHILIPS-HUE-INC'): 68 | 69 | bps = System_sel.baseline_power*System_sel.args[1] #baseline_power PER BULB times the number of bulbs in the system ! 70 | System_sel.setBaselinePowerSystem(bps) 71 | 72 | name_str = '{}#OS {}#BULBS {}#HUBS'.format(System_sel.args[0], System_sel.args[1], System_sel.args[2]) 73 | System_sel.setSetupNameDetails(name_str) 74 | 75 | elif(System_sel.system_ID == 'SMART-METER'): 76 | 77 | bps = System_sel.baseline_power 78 | System_sel.setBaselinePowerSystem(bps) 79 | 80 | name_str = '{}#LINKY'.format(1) 81 | System_sel.setSetupNameDetails(name_str) 82 | 83 | elif(System_sel.system_ID == 'OFFICE-LIGHTNING'): 84 | 85 | bps = System_sel.baseline_power 86 | System_sel.setBaselinePowerSystem(bps) 87 | 88 | name_str = '{}#SENSOR {}#NODES {}#HUBS MODULE'.format(System_sel.args[0], System_sel.args[1], System_sel.args[2]) 89 | System_sel.setSetupNameDetails(name_str) 90 | 91 | elif(System_sel.system_ID == 'other'): 92 | 93 | # other systems can be added here 94 | print('\n Please add another system or select another existing system ! \n') 95 | sys.exit(2) 96 | 97 | else: 98 | raise NameError 99 | 100 | ############################################################################### 101 | 102 | ### PLOT special cases of alpha 103 | 104 | config.plotSpecificAlpha(System_sel) 105 | 106 | ############################################################################### 107 | 108 | ## PLOT the evolution of TPB depending on the number of bulbs in the system 109 | 110 | if (System_sel.system_ID == 'PHILIPS-HUE-LED' or System_sel.system_ID == 'PHILIPS-HUE-CFL' or System_sel.system_ID == 'PHILIPS-HUE-INC'): 111 | 112 | config.plotBulbsImpactHUE(System_sel) 113 | 114 | ############################################################################### 115 | 116 | ### PLOT TPB for a range of alpha 117 | ### PLOT potential savings depending on alpha 118 | ### CHECK if fsolve did its job properly 119 | 120 | config.plotTPB_AlphaRange(System_sel) 121 | 122 | --------------------------------------------------------------------------------