| Conditions | 4 |
| Total Lines | 224 |
| Code Lines | 134 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
| 1 | # -*- coding: utf-8 -*- |
||
| 50 | def main(): |
||
| 51 | # Read data file |
||
| 52 | filename = os.path.join(os.getcwd(), "input_data.csv") |
||
| 53 | try: |
||
| 54 | data = pd.read_csv(filename) |
||
| 55 | except FileNotFoundError: |
||
| 56 | msg = "Data file not found: {0}. Only one value used!" |
||
| 57 | warnings.warn(msg.format(filename), UserWarning) |
||
| 58 | data = pd.DataFrame( |
||
| 59 | { |
||
| 60 | "pv": [0.3, 0.7], |
||
| 61 | "wind": [0.6, 0.5], |
||
| 62 | "demand_el": [500, 400], |
||
| 63 | "demand_th": [400, 300], |
||
| 64 | } |
||
| 65 | ) |
||
| 66 | |||
| 67 | solver = "cbc" |
||
| 68 | |||
| 69 | # Create an energy system and optimize the dispatch at least costs. |
||
| 70 | # ####################### initialize and provide data ##################### |
||
| 71 | datetimeindex = create_time_index(2016, number=len(data)) |
||
| 72 | energysystem = EnergySystem( |
||
| 73 | timeindex=datetimeindex, infer_last_interval=False |
||
| 74 | ) |
||
| 75 | |||
| 76 | # ######################### create energysystem components ################ |
||
| 77 | |||
| 78 | # resource buses |
||
| 79 | bcoal = Bus(label="coal", balanced=False) |
||
| 80 | bgas = Bus(label="gas", balanced=False) |
||
| 81 | boil = Bus(label="oil", balanced=False) |
||
| 82 | blig = Bus(label="lignite", balanced=False) |
||
| 83 | |||
| 84 | # electricity and heat |
||
| 85 | bel = Bus(label="bel") |
||
| 86 | bth = Bus(label="bth") |
||
| 87 | |||
| 88 | energysystem.add(bcoal, bgas, boil, blig, bel, bth) |
||
| 89 | |||
| 90 | # an excess and a shortage variable can help to avoid infeasible problems |
||
| 91 | energysystem.add(Sink(label="excess_el", inputs={bel: Flow()})) |
||
| 92 | # shortage_el = Source(label='shortage_el', |
||
| 93 | # outputs={bel: Flow(variable_costs=200)}) |
||
| 94 | |||
| 95 | # sources |
||
| 96 | energysystem.add( |
||
| 97 | Source( |
||
| 98 | label="wind", |
||
| 99 | outputs={bel: Flow(fix=data["wind"], nominal_value=66.3)}, |
||
| 100 | ) |
||
| 101 | ) |
||
| 102 | |||
| 103 | energysystem.add( |
||
| 104 | Source( |
||
| 105 | label="pv", outputs={bel: Flow(fix=data["pv"], nominal_value=65.3)} |
||
| 106 | ) |
||
| 107 | ) |
||
| 108 | |||
| 109 | # demands (electricity/heat) |
||
| 110 | energysystem.add( |
||
| 111 | Sink( |
||
| 112 | label="demand_el", |
||
| 113 | inputs={bel: Flow(nominal_value=85, fix=data["demand_el"])}, |
||
| 114 | ) |
||
| 115 | ) |
||
| 116 | |||
| 117 | energysystem.add( |
||
| 118 | Sink( |
||
| 119 | label="demand_th", |
||
| 120 | inputs={bth: Flow(nominal_value=40, fix=data["demand_th"])}, |
||
| 121 | ) |
||
| 122 | ) |
||
| 123 | |||
| 124 | # power plants |
||
| 125 | energysystem.add( |
||
| 126 | Transformer( |
||
| 127 | label="pp_coal", |
||
| 128 | inputs={bcoal: Flow()}, |
||
| 129 | outputs={bel: Flow(nominal_value=20.2, variable_costs=25)}, |
||
| 130 | conversion_factors={bel: 0.39}, |
||
| 131 | ) |
||
| 132 | ) |
||
| 133 | |||
| 134 | energysystem.add( |
||
| 135 | Transformer( |
||
| 136 | label="pp_lig", |
||
| 137 | inputs={blig: Flow()}, |
||
| 138 | outputs={bel: Flow(nominal_value=11.8, variable_costs=19)}, |
||
| 139 | conversion_factors={bel: 0.41}, |
||
| 140 | ) |
||
| 141 | ) |
||
| 142 | |||
| 143 | energysystem.add( |
||
| 144 | Transformer( |
||
| 145 | label="pp_gas", |
||
| 146 | inputs={bgas: Flow()}, |
||
| 147 | outputs={bel: Flow(nominal_value=41, variable_costs=40)}, |
||
| 148 | conversion_factors={bel: 0.50}, |
||
| 149 | ) |
||
| 150 | ) |
||
| 151 | |||
| 152 | energysystem.add( |
||
| 153 | Transformer( |
||
| 154 | label="pp_oil", |
||
| 155 | inputs={boil: Flow()}, |
||
| 156 | outputs={bel: Flow(nominal_value=5, variable_costs=50)}, |
||
| 157 | conversion_factors={bel: 0.28}, |
||
| 158 | ) |
||
| 159 | ) |
||
| 160 | |||
| 161 | # combined heat and power plant (chp) |
||
| 162 | energysystem.add( |
||
| 163 | Transformer( |
||
| 164 | label="pp_chp", |
||
| 165 | inputs={bgas: Flow()}, |
||
| 166 | outputs={ |
||
| 167 | bel: Flow(nominal_value=30, variable_costs=42), |
||
| 168 | bth: Flow(nominal_value=40), |
||
| 169 | }, |
||
| 170 | conversion_factors={bel: 0.3, bth: 0.4}, |
||
| 171 | ) |
||
| 172 | ) |
||
| 173 | |||
| 174 | # heat pump with a coefficient of performance (COP) of 3 |
||
| 175 | b_heat_source = Bus(label="b_heat_source") |
||
| 176 | energysystem.add(b_heat_source) |
||
| 177 | |||
| 178 | energysystem.add( |
||
| 179 | Source(label="heat_source", outputs={b_heat_source: Flow()}) |
||
| 180 | ) |
||
| 181 | |||
| 182 | cop = 3 |
||
| 183 | energysystem.add( |
||
| 184 | Transformer( |
||
| 185 | label="heat_pump", |
||
| 186 | inputs={bel: Flow(), b_heat_source: Flow()}, |
||
| 187 | outputs={bth: Flow(nominal_value=10)}, |
||
| 188 | conversion_factors={bel: 1 / 3, b_heat_source: (cop - 1) / cop}, |
||
| 189 | ) |
||
| 190 | ) |
||
| 191 | |||
| 192 | # ################################ optimization ########################### |
||
| 193 | |||
| 194 | # create optimization model based on energy_system |
||
| 195 | optimization_model = Model(energysystem=energysystem) |
||
| 196 | |||
| 197 | # solve problem |
||
| 198 | optimization_model.solve( |
||
| 199 | solver=solver, solve_kwargs={"tee": True, "keepfiles": False} |
||
| 200 | ) |
||
| 201 | |||
| 202 | # write back results from optimization object to energysystem |
||
| 203 | optimization_model.results() |
||
| 204 | |||
| 205 | # ################################ results ################################ |
||
| 206 | |||
| 207 | # subset of results that includes all flows into and from electrical bus |
||
| 208 | # sequences are stored within a pandas.DataFrames and scalars e.g. |
||
| 209 | # investment values within a pandas.Series object. |
||
| 210 | # in this case the entry data['scalars'] does not exist since no investment |
||
| 211 | # variables are used |
||
| 212 | data = views.node(optimization_model.results(), "bel") |
||
| 213 | data["sequences"].info() |
||
| 214 | print("Optimization successful. Showing some results:") |
||
| 215 | |||
| 216 | # see: https://pandas.pydata.org/pandas-docs/stable/visualization.html |
||
| 217 | node_results_bel = views.node(optimization_model.results(), "bel") |
||
| 218 | node_results_flows = node_results_bel["sequences"] |
||
| 219 | |||
| 220 | fig, ax = plt.subplots(figsize=(10, 5)) |
||
| 221 | node_results_flows.plot( |
||
| 222 | ax=ax, kind="bar", stacked=True, linewidth=0, width=1 |
||
| 223 | ) |
||
| 224 | ax.set_title("Sums for optimization period") |
||
| 225 | ax.legend(loc="upper right", bbox_to_anchor=(1, 1)) |
||
| 226 | ax.set_xlabel("Energy (MWh)") |
||
| 227 | ax.set_ylabel("Flow") |
||
| 228 | plt.legend(loc="center left", prop={"size": 8}, bbox_to_anchor=(1, 0.5)) |
||
| 229 | fig.subplots_adjust(right=0.8) |
||
| 230 | |||
| 231 | dates = node_results_flows.index |
||
| 232 | tick_distance = int(len(dates) / 7) - 1 |
||
| 233 | ax.set_xticks(range(0, len(dates), tick_distance), minor=False) |
||
| 234 | if tick_distance > 0: |
||
| 235 | ax.set_xticklabels( |
||
| 236 | [ |
||
| 237 | item.strftime("%d-%m-%Y") |
||
| 238 | for item in dates.tolist()[0::tick_distance] |
||
| 239 | ], |
||
| 240 | rotation=90, |
||
| 241 | minor=False, |
||
| 242 | ) |
||
| 243 | |||
| 244 | plt.show() |
||
| 245 | |||
| 246 | node_results_bth = views.node(optimization_model.results(), "bth") |
||
| 247 | node_results_flows = node_results_bth["sequences"] |
||
| 248 | |||
| 249 | fig, ax = plt.subplots(figsize=(10, 5)) |
||
| 250 | node_results_flows.plot( |
||
| 251 | ax=ax, kind="bar", stacked=True, linewidth=0, width=1 |
||
| 252 | ) |
||
| 253 | ax.set_title("Sums for optimization period") |
||
| 254 | ax.legend(loc="upper right", bbox_to_anchor=(1, 1)) |
||
| 255 | ax.set_xlabel("Energy (MWh)") |
||
| 256 | ax.set_ylabel("Flow") |
||
| 257 | plt.legend(loc="center left", prop={"size": 8}, bbox_to_anchor=(1, 0.5)) |
||
| 258 | fig.subplots_adjust(right=0.8) |
||
| 259 | |||
| 260 | dates = node_results_flows.index |
||
| 261 | tick_distance = int(len(dates) / 7) - 1 |
||
| 262 | ax.set_xticks(range(0, len(dates), tick_distance), minor=False) |
||
| 263 | if tick_distance > 0: |
||
| 264 | ax.set_xticklabels( |
||
| 265 | [ |
||
| 266 | item.strftime("%d-%m-%Y") |
||
| 267 | for item in dates.tolist()[0::tick_distance] |
||
| 268 | ], |
||
| 269 | rotation=90, |
||
| 270 | minor=False, |
||
| 271 | ) |
||
| 272 | |||
| 273 | plt.show() |
||
| 274 | |||
| 278 |