|
| 1 | +#!/usr/bin/env python |
| 2 | +# -*- coding: utf-8 -*- |
| 3 | +""" |
| 4 | +Example script on how to generate a city district with space heating, |
| 5 | +user, stochastic electric, and hot water profiles plus energy systems. |
| 6 | +""" |
| 7 | +from __future__ import division |
| 8 | + |
| 9 | +import shapely.geometry.point as point |
| 10 | +import matplotlib.pyplot as plt |
| 11 | + |
| 12 | +import uesgraphs.visuals as uesvis |
| 13 | + |
| 14 | +import pycity_base.classes.Timer as time |
| 15 | +import pycity_base.classes.Weather as weath |
| 16 | +import pycity_base.classes.Prices as price |
| 17 | +import pycity_base.classes.Environment as env |
| 18 | +import pycity_base.classes.demand.Apartment as apart |
| 19 | +import pycity_base.classes.demand.Occupancy as occ |
| 20 | +import pycity_base.classes.demand.DomesticHotWater as dhw |
| 21 | +import pycity_base.classes.demand.ElectricalDemand as eldem |
| 22 | +import pycity_base.classes.demand.SpaceHeating as spaceheat |
| 23 | +import pycity_base.classes.Building as build |
| 24 | +import pycity_base.classes.CityDistrict as citydist |
| 25 | +import pycity_base.classes.supply.BES as besys |
| 26 | +import pycity_base.classes.supply.Boiler as boil |
| 27 | +import pycity_base.classes.supply.PV as pvsys |
| 28 | + |
| 29 | + |
| 30 | +def run_test(): |
| 31 | + # Define the time discretization for the timer object |
| 32 | + timestep = 3600 # in seconds |
| 33 | + |
| 34 | + # Define the total number of timesteps (in this case for one year) |
| 35 | + nb_timesteps = int(365 * 24 * 3600 / timestep) |
| 36 | + |
| 37 | + # Generate environment with timer, weather, and prices objects |
| 38 | + # ###################################################################### |
| 39 | + timer = time.Timer(timeDiscretization=timestep, |
| 40 | + timestepsTotal=nb_timesteps) |
| 41 | + weather = weath.Weather(timer=timer) |
| 42 | + prices = price.Prices() |
| 43 | + |
| 44 | + environment = env.Environment(timer=timer, weather=weather, prices=prices) |
| 45 | + |
| 46 | + # Generate city district object |
| 47 | + # ###################################################################### |
| 48 | + city_district = citydist.CityDistrict(environment=environment) |
| 49 | + # Annotations: To prevent some methods of subclasses uesgraph / nx.Graph |
| 50 | + # from failing (e.g. '.subgraph()) environment is set as optional input |
| 51 | + # parameter. However, it is necessary to use an environment object as |
| 52 | + # input parameter to initialize a working cityDistrict object! |
| 53 | + |
| 54 | + # Empty dictionary for building positions |
| 55 | + dict_pos = {} |
| 56 | + |
| 57 | + # Generate shapely point positions |
| 58 | + dict_pos[0] = point.Point(0, 0) # (x, y) |
| 59 | + dict_pos[1] = point.Point(20, 0) |
| 60 | + |
| 61 | + # Use for loop to generate two identical building objects for city |
| 62 | + # district |
| 63 | + # ###################################################################### |
| 64 | + for i in range(2): |
| 65 | + living_area = 200 # in m2 |
| 66 | + spec_sh_dem = 160 # Specific space heating demand in kWh/m2 |
| 67 | + number_occupants = 3 # Total number of occupants |
| 68 | + |
| 69 | + # Generate space heating demand object (holding loadcurve attribute |
| 70 | + # with space heating power) |
| 71 | + heat_demand = spaceheat.SpaceHeating( |
| 72 | + environment=environment, |
| 73 | + method=1, # Standard load profile |
| 74 | + livingArea=living_area, # in m2 |
| 75 | + specificDemand=spec_sh_dem) # in kWh/m2 |
| 76 | + |
| 77 | + # Generate occupancy object with stochastic user profile |
| 78 | + occupancy = occ.Occupancy(environment=environment, |
| 79 | + number_occupants=number_occupants) |
| 80 | + |
| 81 | + # Generate electrical demand object |
| 82 | + el_dem_stochastic = eldem.ElectricalDemand( |
| 83 | + environment=environment, |
| 84 | + method=2, # stochastic Richardson profile (richardsonpy) |
| 85 | + total_nb_occupants=number_occupants, # Number of occupants |
| 86 | + randomizeAppliances=True, # Random choice of installed appliances |
| 87 | + lightConfiguration=10, # Light bulb configuration nb. |
| 88 | + occupancy=occupancy.occupancy, # Occupancy profile (600 s resol.) |
| 89 | + prev_heat_dev=True, # Prevent space heating and hot water devices |
| 90 | + annualDemand=None, # Annual el. demand in kWh could be used for |
| 91 | + do_normalization=False) # rescaling (if do_normalization is True) |
| 92 | + # Annotation: The calculation of stochastic electric load profiles |
| 93 | + # is time consuming. If you prefer a faster method, you can either |
| 94 | + # hand over an own array-like load curve (method=0) or generate a |
| 95 | + # standardized load profile (SLP) (method=1) |
| 96 | + |
| 97 | + # Generate domestic hot water demand object |
| 98 | + dhw_obj = dhw.DomesticHotWater( |
| 99 | + environment=environment, |
| 100 | + tFlow=60, # DHW output temperature in degree Celsius |
| 101 | + method=2, # Stochastic dhw profile |
| 102 | + supplyTemperature=25, # DHW inlet flow temperature in degree C. |
| 103 | + occupancy=occupancy.occupancy) # Occupancy profile (600 s resol.) |
| 104 | + |
| 105 | + # Generate apartment and add demand durves |
| 106 | + apartment = apart.Apartment(environment) |
| 107 | + apartment.addMultipleEntities([heat_demand, |
| 108 | + el_dem_stochastic, |
| 109 | + dhw_obj]) |
| 110 | + |
| 111 | + # Generate building and add apartment |
| 112 | + building = build.Building(environment) |
| 113 | + building.addEntity(apartment) |
| 114 | + |
| 115 | + # Add buildings to city district |
| 116 | + city_district.addEntity(entity=building, |
| 117 | + position=dict_pos[i]) |
| 118 | + |
| 119 | + # Access information on city district object instance |
| 120 | + # ###################################################################### |
| 121 | + print('Get number of building entities:') |
| 122 | + print(city_district.get_nb_of_building_entities()) |
| 123 | + print() |
| 124 | + |
| 125 | + print('Get list with node ids of building entities:') |
| 126 | + print(city_district.get_list_build_entity_node_ids()) |
| 127 | + print() |
| 128 | + |
| 129 | + print('Get city district overall space heating power load curve:') |
| 130 | + print(city_district.get_aggr_space_h_power_curve()) |
| 131 | + print() |
| 132 | + |
| 133 | + # We can use the Visuals class of uesgraphs to plot the city district |
| 134 | + |
| 135 | + # Generate uesgraphs visuals object instance |
| 136 | + uesvisuals = uesvis.Visuals(uesgraph=city_district) |
| 137 | + |
| 138 | + fig = plt.figure() |
| 139 | + ax = fig.gca() |
| 140 | + ax = uesvisuals.create_plot_simple(ax=ax) |
| 141 | + plt.show() |
| 142 | + plt.close() |
| 143 | + |
| 144 | + # Access buildings |
| 145 | + # ###################################################################### |
| 146 | + # As city_district is a networkx graph object, we can access the building |
| 147 | + # entities with the corresponding building node, |
| 148 | + # Pointer to building object with id 1001: |
| 149 | + building_1001 = city_district.nodes[1001]['entity'] |
| 150 | + |
| 151 | + print('Get building 1001 electric load curve:') |
| 152 | + print(building_1001.get_electric_power_curve()) |
| 153 | + print() |
| 154 | + |
| 155 | + # Add energy systems to buildings |
| 156 | + # ###################################################################### |
| 157 | + # We can also add building energy systems (BES) to each building object |
| 158 | + |
| 159 | + # Generate boiler object |
| 160 | + boiler = boil.Boiler(environment=environment, |
| 161 | + qNominal=10000, # Boiler thermal power in Watt |
| 162 | + eta=0.85) # Boiler efficiency |
| 163 | + |
| 164 | + # Generate PV module object |
| 165 | + pv = pvsys.PV(environment=environment, |
| 166 | + area=30, # Area in m2 |
| 167 | + eta=0.15) # Electrical efficiency at NOCT conditions |
| 168 | + |
| 169 | + # Instantiate BES (container object for all energy systems) |
| 170 | + bes = besys.BES(environment) |
| 171 | + |
| 172 | + # Add energy systems to bes |
| 173 | + bes.addMultipleDevices([boiler, pv]) |
| 174 | + |
| 175 | + # Add bes to building 1001 |
| 176 | + building_1001.addEntity(entity=bes) |
| 177 | + |
| 178 | + print('Does building 1001 has a building energy system (BES)?') |
| 179 | + print(building_1001.hasBes) |
| 180 | + |
| 181 | + # Access boiler nominal thermal power |
| 182 | + print('Nominal thermal power of boiler in kW:') |
| 183 | + print(building_1001.bes.boiler.qNominal / 1000) |
| 184 | + |
| 185 | +if __name__ == '__main__': |
| 186 | + # Run program |
| 187 | + run_test() |
0 commit comments