Example #1
0
	def categorize_residential_building(self):
		"""
		Categorizes building according to TABULA typologies. 
		Construction year class and building type are calculated by comparing the residential
		building ground floor area (gfa) with the GFA of typical buildings (from TABULA).
		Values are adapted to building stock statistics.
		
		returns:
			self.class_year	  <tuple>	(int, str)
			self.btype		  <tuple>	(int, str)
		"""
		
		gfa = self.env_areas[2]
		
		# get size of GFA matrix
		rows 			= len(self.GFA)		# construction year class
		cols 			= len(self.GFA[0])	# building type
		
		# initialize distance vectors
		distance        = np.zeros(rows * cols)
		distance_inv    = np.zeros(rows * cols)
		row_col 	    = [[] for _ in range(rows * cols)]
		t_distance_inv  = 0
		kkk 		    = 0
		
		# calculate inverse of distances
		# 1/d is used so that the minimum distance has a higher probability
		for iii in range(0, rows):
			for jjj in range(0, cols):
				distance[kkk]     = abs(self.GFA[iii][jjj] - gfa) + 0.01 # "+ 0.001" to avoid having x/0
				distance_inv[kkk] = (1.0 / distance[kkk]) * self.STOCK_RES[iii, jjj]
				row_col[kkk] 	  = [iii, jjj]
				t_distance_inv   += distance_inv[kkk] 
				kkk              += 1
		
		# normalize inverse distance
		norm_distance   = distance_inv / t_distance_inv

		# get cumulative density function
		cdf             = np.cumsum(norm_distance)

		# generate random number
		rnd       	    = np.random.uniform(0, 1, 1)

		# check random number with cdf
		index 			= np.argmax(rnd < cdf)
		
		# Construction year class
		self.year_class = UrbanHeatPro.year_class_to_tuple(self.use[0], row_col[index][0])
		
		# Building type
		self.btype 		= UrbanHeatPro.building_type_to_tuple(self.use[0], row_col[index][1])
Example #2
0
	def analyze_building_stock_per_run(self, run, result_dir_run):
		"""
		Compares the distribution of the synthetic building stock generated per run
		with the statistics.
		"""
			
		# RESIDENTIAL
		# total buildings
		count_res  = len(self.my_city.energy_per_building[self.my_city.energy_per_building[:, 1] == 3])
		
		for year_class in range(10):
			for btype in range(4):
		
				# extract all buildings B with specific year_class, btype and use
				c0  = self.my_city.energy_per_building[:, 1] == 3  # RESIDENTIAL
				c1  = self.my_city.energy_per_building[:, 2] == year_class
				c2  = self.my_city.energy_per_building[:, 3] == btype
				B   = self.my_city.energy_per_building[c0 * c1 * c2]
			
				# add building distribution to category
				self.bstock_res[run][year_class][btype]   = len(B)/float(count_res)
		
		# NON-RESIDENTIAL
		count_nres = len(self.my_city.energy_per_building[self.my_city.energy_per_building[:, 1] != 3])
		
		for year_class in range(5):
			
			# extract all buildings B with specific year_class, btype and use
			c0  = self.my_city.energy_per_building[:, 1] != 3  # NON-RESIDENTIAL
			c1  = self.my_city.energy_per_building[:, 2] == year_class
			B   = self.my_city.energy_per_building[c0 * c1]
			
			# add building distribution to category
			self.bstock_nres[run][year_class] 			  = len(B)/float(count_nres)
			count_nres += 1
					
		# Plots
		# Building distribution per category from statistics [%]
		stat_res   = self.building_stock_stats[8]
		stat_nres  = self.building_stock_stats[9]
		
		# plot imshow to compare with statistics
		fig_name    = '{}/BuildingStock_res_{}.png'.format(result_dir_run, run)
		UrbanHeatPro.plot_imshow_comparison(3, self.bstock_res[run], stat_res, fig_name, cmap = 'RdBu')
		#
		fig_name    = '{}/BuildingStock_nres_{}.png'.format(result_dir_run, run)
		UrbanHeatPro.plot_imshow_comparison(0, self.bstock_nres[run], stat_nres, fig_name, cmap = 'RdBu')
Example #3
0
	def categorize_non_residential_building(self):
		"""
		int	construction year class
		0	< 1918
		1	1919 - 1976
		2	1977 - 1983
		3	1984 - 1994
		4	> 1995

		>>> Statistics on the non-residential buildings stock are missing
		"""
		
		# assign random construction year class
		year_class_int = randint(0, 4)
		
		self.year_class = UrbanHeatPro.year_class_to_tuple(self.use[0], year_class_int)
		self.btype		= UrbanHeatPro.building_type_to_tuple(self.use[0], self.btype_int)
Example #4
0
	def analyze_building_stock_per_sim(self):
		"""
		Compares the MEAN distribution of the synthetic building stock generated per run
		with the statistics.
		"""
		
		# Building distribution per category from statistics [%]
		stat_res   = self.building_stock_stats[8]
		stat_nres  = self.building_stock_stats[9]
		
		# Simulation building stock results
		mean_res   = self.bstock_res.mean(axis = 0)
		mean_nres  = self.bstock_nres.mean(axis = 0)
		
		# plot imshow to compare with statistics
		fig_name    = '{}/BuildingStock_res.png'.format(self.result_dir)
		UrbanHeatPro.plot_imshow_comparison(3, mean_res, stat_res, fig_name, cmap = 'RdBu')
		#
		fig_name    = '{}/BuildingStock_nres.png'.format(self.result_dir)
		UrbanHeatPro.plot_imshow_comparison(0, mean_nres, stat_nres, fig_name, cmap = 'RdBu')
Example #5
0
    def plot_energy(self, space_heating=True, hot_water=True, total=True):
        """
		Plots histogram of aggregated heat demand for all simulations
		"""

        if space_heating:
            ylabel = 'Space Heating Demand [GWh]'
            fig_name = '{}/SpaceHeatingDemand_hist.png'.format(self.result_dir)
            UrbanHeatPro.plot_histogram(self.space_heating_energy,
                                        ylabel,
                                        fig_name,
                                        factor=1e9)

        if hot_water:
            ylabel = 'Hot Water Demand [GWh]'
            fig_name = '{}/HotWaterDemand_hist.png'.format(self.result_dir)
            UrbanHeatPro.plot_histogram(self.hot_water_energy,
                                        ylabel,
                                        fig_name,
                                        factor=1e9)

        if total:
            ylabel = 'Total Heat Demand [GWh]'
            fig_name = '{}/TotalHeatDemand_hist.png'.format(self.result_dir)
            UrbanHeatPro.plot_histogram(self.total_energy,
                                        ylabel,
                                        fig_name,
                                        factor=1e9)
Example #6
0
    def plot_timeseries(self,
                        space_heating=True,
                        hot_water=True,
                        total=True,
                        xticks=('month', 3)):
        """
		"""

        if space_heating:
            fig_name = '{}/SpaceHeatingDemand_{}.png'.format(
                self.result_dir, self.rid)

            UrbanHeatPro.plot_timeseries(self.dt_vector, \
              [self.space_heating_power], ['Space heating demand'], \
              fig_name, xticks = xticks, \
              ynumticks = 'auto', ylabel = 'Power [kW]', ylim0 = True, yfactor = 1e3)

        if hot_water:
            fig_name = '{}/HotWaterDemand_{}.png'.format(
                self.result_dir, self.rid)

            UrbanHeatPro.plot_timeseries(self.dt_vector, \
              [self.hot_water_power], ['Hot water demand'], \
              fig_name, xticks = xticks, \
              ynumticks = 'auto', ylabel = 'Power [kW]', ylim0 = True, yfactor = 1e3)

        if total:
            fig_name = '{}/TotalHeatDemand_{}.png'.format(
                self.result_dir, self.rid)

            UrbanHeatPro.plot_stacked_timeseries(self.dt_vector, \
              [self.hot_water_power, self.space_heating_power], \
              ['Hot water', 'Space heating'], \
              fig_name, xticks = xticks, \
              ynumticks = 'auto', ylabel = 'Power [kW]', ylim0 = True, yfactor = 1e3)
Example #7
0
	def plot_timeseries(self, \
				space_heating = True, Tb = False, \
				hot_water = True, \
				total = True):
		"""
		Plots heat demand timeseries
		"""
		
		if space_heating:
			fig_name = '{}/SpaceHeatingDemand_{}_{}_{}_{}.png'.format(self.result_dir, \
							self.use[0], self.year_class[0], self.btype[0], self.bid)
			
			UrbanHeatPro.plot_timeseries(self.dt_vector, \
					[self.space_heating_power], ['Space heating demand'], \
					fig_name, xticks = ('month', 3), \
					ynumticks = 'auto', ylabel = 'Power [kW]', ylim0 = True, yfactor = 1e3)
				
		if Tb:
			fig_name = '{}/BuildingTemperature_{}_{}_{}_{}.png'.format(self.result_dir, \
							self.use[0], self.year_class[0], self.btype[0], self.bid)
			
			UrbanHeatPro.plot_timeseries(self.dt_vector, \
			[self.Tamb, self.Tb], ['T_amb', 'T_b'], \
					fig_name, xticks = ('month', 3), \
					ynumticks = 'auto', ylabel = 'Temperature [degC]', ylim0 = False, yfactor = 1)
									
		if hot_water:
			fig_name = '{}/HotWaterDemand_{}_{}_{}_{}.png'.format(self.result_dir, \
							self.use[0], self.year_class[0], self.btype[0], self.bid)
			
			UrbanHeatPro.plot_timeseries(self.dt_vector, \
					[self.hot_water_power], ['Hot water demand'], \
					fig_name, xticks = ('month', 3), \
					ynumticks = 'auto', ylabel = 'Power [kW]', ylim0 = True, yfactor = 1e3)

		if total:
			fig_name = '{}/TotalHeatDemand_{}_{}_{}_{}.png'.format(self.result_dir, \
							self.use[0], self.year_class[0], self.btype[0], self.bid)
			
			UrbanHeatPro.plot_stacked_timeseries(self.dt_vector, \
					[self.hot_water_power, self.space_heating_power], \
					['Hot water', 'Space heating'], \
					fig_name, xticks = ('month', 3), \
					ynumticks = 'auto', ylabel = 'Power [kW]', ylim0 = True, yfactor = 1e3)	
Example #8
0
    def plot_power(self, space_heating=True, hot_water=True, total=True):
        """
		Plot min, max, and mean power values for each time step.
		"""
        if space_heating:
            min = self.space_heating_power.min(axis=1)
            max = self.space_heating_power.max(axis=1)
            mean = self.space_heating_power.mean(axis=1)

            fig_name = '{}/SpaceHeatingDemand_ts.png'.format(self.result_dir)

            UrbanHeatPro.plot_timeseries(self.dt_vector, \
              [min, max, mean], ['min', 'max', 'mean'], \
              fig_name, xticks = ('month', 3), \
              ynumticks = 'auto', ylabel = 'Space Heating Demand [MW]', ylim0 = True, yfactor = 1e6)

        if hot_water:
            min = self.hot_water_power.min(axis=1)
            max = self.hot_water_power.max(axis=1)
            mean = self.hot_water_power.mean(axis=1)

            fig_name = '{}/HotWaterDemand_ts.png'.format(self.result_dir)

            UrbanHeatPro.plot_timeseries(self.dt_vector, \
              [min, max, mean], ['min', 'max', 'mean'], \
              fig_name, xticks = ('month', 3), \
              ynumticks = 'auto', ylabel = 'Hot Water Demand [MW]', ylim0 = True, yfactor = 1e6)

        if total:
            min = self.total_power.min(axis=1)
            max = self.total_power.max(axis=1)
            mean = self.total_power.mean(axis=1)

            fig_name = '{}/TotalHeatDemand_ts.png'.format(self.result_dir)

            UrbanHeatPro.plot_timeseries(self.dt_vector, \
              [min, max, mean], ['min', 'max', 'mean'], \
              fig_name, xticks = ('month', 3), \
              ynumticks = 'auto', ylabel = 'Heat Demand [MW]', ylim0 = True, yfactor = 1e6)
Example #9
0
	def calculate_building_envelope_areas(self):
		"""
		Calculates building envelope areas (wall, roof and window) depending on the 
		building use: 
		Residential: areas are calculated according to building typologies in TABULA.
					 To obtain the typology (construction year class and building type)
					 the gfa is matched to the typology GFA.
		Non-residential: number of floors and window-to-wall ratio are
					 derived from statistics and used to calculate the building areas.
					 Construction year class is also derived from statistics.
		
		An area_correction_factor is included since not the whole floor area is heated.
		From VDI 3807-2.
		
		
		returns:
			self.env_areas		<list>		[Roof, Walls, Floor (gfa), Window] in m2
			self.heated_area 	<float>		Total building heated area
		"""
			
		if (self.use[0] == 3): # RESIDENTIAL
		
			# Area correction factor for calculating heated areas
			area_correction_factor = 0.85
			
			# Conditioned (heated) GFA
			self.gfa_h = self.env_areas[2] * area_correction_factor
		
			# check if building typology is given
			if self.building_typology:			
				self.year_class           = UrbanHeatPro.year_class_to_tuple(self.use[0], self.year_class_int) # Construction year class (int, str)
				self.btype				  = UrbanHeatPro.building_type_to_tuple(self.use[0], self.btype_int)	    # Building type (int, str)
		
			else:
				# assign building typology from statistics	
				# check that the building data exists as C-values are not available for all buildings
				building_exists = False
				while building_exists == False:
					self.categorize_residential_building()
					a = self.C_RES[2][self.year_class[0]][self.btype[0]] # C_floor value
					b = self.GFA[self.year_class[0]][self.btype[0]]
					if (a > 0.0 and b > 0.0):
						building_exists = True
			
			# Floor-to-floor height
			# from http://www.ctbuh.org/HighRiseInfo/TallestDatabase/Criteria/HeightCalculator/tabid/1007/language/en-GB/Default.aspx
			# self.f2f_height = (randint(30, 32) / 10.0) # m
			# from TABULA
			self.f2f_height = 2.5 # m
			
			# Number of floors
			self.floors 	= self.FLOORS[self.year_class[0]][self.btype[0]] * (1 + (1 - area_correction_factor))

			# Building areas
			### Roof
			self.env_areas[0] 	= self.ARATIO[0][self.year_class[0]][self.btype[0]] * self.gfa_h
			### Wall
			self.env_areas[1]	= self.ARATIO[1][self.year_class[0]][self.btype[0]] * self.gfa_h * self.free_walls					
			### Window
			self.env_areas[3] 	= self.ARATIO[2][self.year_class[0]][self.btype[0]] * self.gfa_h
						
			for j in range(4):
				self.window_areas[j] = self.env_areas[3] * self.WRATIO_ORIENTATION[5 * j + self.btype[0]]

			
		else: # NON-RESIDENTIAL	
		
			# Area correction factor for calculating heated areas
			area_correction_factor = (randint(6, 8) / 10.0)
			
			# Conditioned (heated) GFA
			self.gfa_h = self.env_areas[2] * area_correction_factor
		
			# Construction year class
			self.categorize_non_residential_building()
			
			# Floor-to-floor height
			# from http://www.ctbuh.org/HighRiseInfo/TallestDatabase/Criteria/HeightCalculator/tabid/1007/language/en-GB/Default.aspx
			self.f2f_height = (randint(30, 39) / 10.0) # m
			
			# Number of floors
			# >>> Source missing
			lower_limit     = 1
			upper_limit     = 3
			self.calculate_number_of_floors(lower_limit, upper_limit)
			
			# Building areas
			### Roof
			self.env_areas[0]   = self.gfa_h
			### Wall
			width 				= np.sqrt(self.gfa_h) # [m] building is assumed to be a cube
			self.env_areas[1]   = self.free_walls * self.floors * self.f2f_height * width
			### Window
			# >>> Add Window-to-Wall ratio for the different building types
			# >>> Source missing
			self.env_areas[3]   = (randint(1, 4) / 10.0) * self.env_areas[1]

			# Window areas oriented to [east, south, west, north]
			for j in range(4):
				self.window_areas[j] = self.env_areas[3] * self.WRATIO_ORIENTATION[5 * j + 4]			
			
		# Total heated area (reference area in TABULA) in m2
		self.heated_area = self.gfa_h * self.floors
		
		# Total living space
		self.living_area = self.gfa_h * self.floors * (1 + (1 - area_correction_factor))
Example #10
0
	def __init__(self, dt_vectors, resolution, Tamb, I, _space_heating, _hot_water, \
					Tb0_str, dTset, dT_per_hour, eta, thermal_inertia, building_stock_stats, \
					bid, use, gfa, free_walls, lat, lon, distance2hp, building_typology, year_class_int, btype_int, \
					refurbishment_level, _active_population, _solar_gains, _internal_gains, \
					_night_set_back, schedule_nsb, T_nsb, power_reduction, \
					Tw, dhw_prob, hw_tank_limit, hw_flow, \
					day_vector, seasonal_vector, min_vector, \
					result_dir, plot, save, debug):
		
		# General data
		# --------------------------------------------------
		# Building data
		self.bid                  = bid							# Building id
		self.use                  = UrbanHeatPro.building_use_to_tuple(use) # Building use (int, str)
		self.free_walls           = free_walls					# Number of walls in contact with Tamb
		self.coords				  = (lat, lon)					# Coordinates of building centroid
		self.building_typology	  = building_typology
		self.year_class_int		  = year_class_int
		self.btype_int			  = btype_int
		self.year_class           = None 						# Construction year class (int, str)
		self.btype				  = None 						# Building type (int, str)
		self.env_areas			  = [0, 0, gfa, 0] 				# Envelope areas [Roof, Walls, Floor (gfa), Window]
		self.window_areas		  = [0, 0, 0, 0]				# Window area oriented to the [east, south, west, north]
		self.floors				  = 0							# number of floors
		self.f2f_height			  = 0				    		# floor to floor height [m]
		self.heated_area		  = 0							# total heated area (reference area) [m2]
		self.living_area		  = 0							# total living area [m2]
		self.dwellings			  = 0							# number of dwellings in building
		self.dwelling_size_cat	  = 0							# dwelling size category to calculate household size
		
		# Simulation
		self.dt_vector    		  = dt_vectors[0] 				# Vector of time steps as datetime objects
		self.dt_vector_excel	  = dt_vectors[1] 				# Vector of time steps as excel date
		self.nts          		  = len(self.dt_vector)			# Number of time steps
		self.resolution			  = resolution					# Temporal resolution in min
		self._space_heating		  = _space_heating				# Calculate space heating demand?
		self._hot_water			  = _hot_water					# Calculate hot water demand?
	
		# External factors	
		self.Tamb         		  = Tamb		 				# Ambient temperature vector in degC
		self.I	         	  	  = I					 		# Solar radiation vector in W/m2 [I_Gh, I_Dh, I_ex, hs]
		self.eta          		  = eta			 				# Heating process efficiency
		self.thermal_inertia	  = thermal_inertia				# Thermal inertia of the heating system
		
		# Result directory
		self.result_dir			  = result_dir					# Directory where results are stored
		
		
		# Space heating demand
		# --------------------------------------------------
		# Building stock statistics I
		self.GFA  				  = building_stock_stats[0][0]  # GFA of building typologies (TABULA)
		self.ARATIO 			  = building_stock_stats[0][1]  # Area ratio [Roof, Wall, Window]
		self.WRATIO_ORIENTATION	  = building_stock_stats[0][2]  # Window ratio [East, South, West, North]
		self.FLOORS				  = building_stock_stats[0][3]  # Number of floors
		self.U_RES				  = building_stock_stats[0][4]  # U-values for residential buildings
		self.V_RES				  = building_stock_stats[0][5]  # Air flow rate (ventilation losses) for residential
		self.C_RES				  = building_stock_stats[0][6]  # Thermal cap for residential buildings
		self.REFURBISHED_RES	  = building_stock_stats[0][7]  # Percentage of residential refurbished buildings
		self.SINGLE_DWELLING	  = building_stock_stats[0][8]  # Percentage of single dwellings for SFH and TH
		self.HOUSEHOLD_SIZE		  = building_stock_stats[0][9]  # Household size for dwelling size categories
		self.U_NRES				  = building_stock_stats[0][10] # U-values for non-residential buildings
		self.V_NRES				  = building_stock_stats[0][11]	# Air flow rate (ventilation losses) for non-residential
		self.C_NRES				  = building_stock_stats[0][12]	# Thermal cap for non-residential buildings
		self.TSET				  = building_stock_stats[0][13] # Target temperatures per building use
		self.SCHEDULE			  = building_stock_stats[0][14]	# Active hours per building use
		self.STOCK_RES			  = building_stock_stats[0][15] # Building stock statistics for residential
		self.STOCK_NRES			  = building_stock_stats[0][16] # Building stock statistics for non-residential
		
		# Building thermal properties
		self.U                    = 0.							# Transmission losses (U-value) [W/K]
		self.V					  = 0.							# Ventilation losees [W/K]
		self.C                    = 0.							# Thermal capacitance [J/K]
		self.Tau                  = 0.							# Time constant [s]
		self.Tb0_str			  = Tb0_str						# Initial building temperature as string: 'ambient' or 'Tset'
		self.Tb0                  = 0.							# Initial building temperature
		self.Tset                 = 0.							# [Target temperature, dT]  [degC]
		self.dTset				  = dTset						# Delta temperature (for Tset_min, Tset_max)
		self.dT_per_hour		  = dT_per_hour					# Maximum dT allowed in building per hour [degC]
		
		# Activity and occupancy in building
		self._active_population	  = _active_population			# Consider active population for occupancy vector
		self.active_hours         = [[0, 0], [0, 0]]			# Building active hours [(start0, end0), (start1, end1)]
		self.activity_vector	  = np.ones([self.nts]) * 1. 	# Building activity vector
		self.occupancy_vector	  = np.ones([self.nts]) * 1.	# Number of occupants in building per timestep
		self.household_vector	  = []							# Vector of households occupancy
		self.occupants			  = 0							# Number of occupants in building
		self.occupied			  = 1.							# Is building occupied?
		self.perc_occupied		  = 0.							# Percentage of occupied dwellings in building
		
		# Heat gains
		self._solar_gains	  	  = _solar_gains
		self._internal_gains  	  = _internal_gains
		
		# DSM
		self.refurbishment_level  = refurbishment_level
		self._night_set_back  	  = _night_set_back				# Share of buildings with nsb
		self.schedule_nsb		  = schedule_nsb				# [start, end] of nsb in h
		self.T_nsb		  		  = T_nsb						# Night set-back temperature in degC
		self.power_reduction 	  = power_reduction				# Percentage of power reduced (as decimal)
		
		# Results
		self.space_heating_power  = np.zeros([self.nts]) 		# Power required so that Tb >= Tset in W
		self.solar_gains  		  = np.zeros([self.nts]) 		# Power required so that Tb >= Tset in W
		self.internal_gains  	  = np.zeros([self.nts]) 		# Power required so that Tb >= Tset in W
		self.Tb  				  = np.zeros([self.nts]) 		# Building temp in degC
		self.space_heating_energy = 0.							# Aggregated heating demand in Wh
		self.space_heating_energy_per_area = 0.					# Aggregated heating demand in kWh/m2

		
		# Hot water demand
		# --------------------------------------------------
		# Domestic hot water consumption
		self.Tw					  = Tw							# Hot water temperature in [degC]
		self.daily_DHW			  = 0.							# Daily domestic hot water consumption in m3
		self.dhw_prob			  = dhw_prob					# Probabilities for dhw-loads
		self.hw_tank_capacity	  = 0.							# Hot water tank capacity in m3
		self.hw_tank_volume_t0	  = 0.							# Initial state of hot water tank in m3
		self.hw_tank_limit	   	  = hw_tank_limit 				# Hot water tank limit as perc (decimal)
		self.hw_flow		      = hw_flow				    	# Flow to refill hot water tank in L/min
		
		# Seasonality
		self.day_vector			  = day_vector					# Vector of days in simulation time frame
		self.seasonal_vector	  = seasonal_vector				# Sinusoidal function for seasonal variations of DHW consumption
		
		# Results
		self.hot_water_m3		  = np.zeros([self.nts])		# Hot water demand in m3 (instantaneous demand)
		self.hot_water_tank_m3	  = np.zeros([self.nts])		# Hot water demand in m3 (tank demand)
		self.hot_water_power      = np.zeros([self.nts])		# Hot water demand in W
		self.hot_water_energy	  = 0.							# Aggregated hot water demand in Wh
		self.dhw_debug	 		  = np.zeros([self.nts, 20])	# Hot water demand data per time step
		
		
		# Total heating energy demand
		# --------------------------------------------------
		# Instantaneous demand
		self.total_power   		  = np.zeros([self.nts])		# Total heat demand in W
		self.total_energy	  	  = 0.							# Aggregated total heat demand in Wh
		
		# Delayed demand
		self.min_vector			  = min_vector					# Vector of simulation time steps in minutes
		self.distance2hp		  = distance2hp					# Distance to heat plant in m
		self.delay				  = 0.							# Delay due to distance in min
		self.delayed_min_vector	  = np.zeros([self.nts])		# Vector of delayed time steps in min
		self.total_power_delayed  = np.zeros([self.nts])		# Delayed total heat demand in W
		self.total_energy_delayed = 0.							# Delayed total energy demand in Wh
		

		# Reporting
		# --------------------------------------------------
		self.plot				  = plot
		self.save				  = save
		self.debug				  = debug
Example #11
0
    def calculate_typical_days(self):
        """
		Calculates typical days based on Tamb timeseries.
		Based on Nahmmacher et al. (2016), Carpe diem: A novel approach to select 
		representative days for long-term power system modeling.
		"""

        if self.debug != 0:
            print('Typical days: {}'.format(self.number_of_typ_days))

        # 1. Divide data into days
        # ------------------------
        ## initialize variables
        days_in_year = len(self.Tamb) // ((24 * 60) // self.resolution)
        data_in_days = np.zeros((days_in_year, (24 * 60) // self.resolution),
                                dtype=float)
        row_start = np.zeros((days_in_year), dtype=int)
        row_end = np.zeros((days_in_year), dtype=int)

        ## arrange data
        data = self.Tamb
        for day in range(days_in_year):
            if (day == 0):
                row_start[day] = 0
                row_end[day] = 24 * 60 / self.resolution
            else:
                row_start[day] = row_end[day - 1]
                row_end[day] = 24 * 60 / self.resolution + row_start[day]

            data_in_days[day, :] = np.reshape(
                data[row_start[day]:row_end[day]], (24, ))

        # 2. Hierarchical clustering
        # --------------------------
        # Linkage matrix using Ward's method
        # Ward's algorithm groups similar days based on a dstance measure that leads to clusters with a minimum inner-cluster
        # variance.
        Z = linkage(data_in_days, 'ward')

        # 3. Number of clusters
        # -----------------------
        # Number of clusters
        max_c = self.number_of_typ_days
        clusters = fcluster(Z, max_c, criterion='maxclust')

        # Distribution of historical days sorted by months and clusters
        ## Number of clusters
        number_of_clusters = max(clusters)

        ## Months
        month_names = [
            'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
            'Oct', 'Nov', 'Dec', '', 'Year'
        ]
        days_in_month = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
        month_cumsum = np.cumsum(days_in_month)

        ## Sorted clusters by temperature
        ### sort clusters
        mean_clusters = np.zeros((number_of_clusters, 24))
        max_mean_clusters = np.zeros(number_of_clusters)
        for c in range(1, number_of_clusters + 1):
            indices_in_cluster = np.where(clusters == c)[0]
            mean_clusters[c - 1, :] = np.mean(
                data_in_days[indices_in_cluster, :], axis=0)
            max_mean_clusters[c - 1] = np.max(mean_clusters[c - 1, :])

        # sorted_clusters = np.argsort(max_mean_clusters)[::-1] # Hot days first
        sorted_clusters = np.argsort(max_mean_clusters)  # Cold days first

        ### substitute ordered clusters
        clusters_copy = copy.deepcopy(clusters)
        for iii, c in enumerate(sorted_clusters):
            indices_in_cluster = np.where(clusters_copy == c + 1)[0]
            clusters[indices_in_cluster] = iii + 1

        ## Annual share per cluster
        clusters_per_month = np.zeros((number_of_clusters, 14))
        for c in range(number_of_clusters):
            clusters_per_month[c,
                               13] = np.sum(clusters == c + 1) / days_in_year

            for m in range(12):  # month
                # group per month
                if m == 0:
                    c_start = 0
                else:
                    c_start = month_cumsum[m - 1]
                c_end = month_cumsum[m]
                days_per_month = np.zeros(days_in_month[m])
                days_per_month = clusters[c_start:c_end]
                clusters_per_month[c, m] = np.sum(days_per_month == c +
                                                  1) / days_in_month[m]

        # 4. Deriving representative days
        # -------------------------------
        # All historical days grouped into the same cluster will be repersented by the
        # same representative day. The representative day for each cluster is the
        # historical day that with the min distance to the average day.

        min_distance_index_c = np.zeros(number_of_clusters, dtype=int)
        min_distance_index_y = np.zeros(number_of_clusters, dtype=int)
        min_distance_day = np.zeros((number_of_clusters, 24))
        avg_day = np.zeros((number_of_clusters, 24))

        for c in range(1, number_of_clusters + 1):
            indices_in_cluster = np.where(clusters == c)[0]

            if len(indices_in_cluster) > 1:

                # Representative day
                ## append average and historical days
                avg_day[c - 1, :] = np.mean(
                    data_in_days[indices_in_cluster, :], axis=0)
                historical_days = data_in_days[indices_in_cluster, :]
                data_to_compare = np.append(np.array([avg_day[c - 1, :]]),
                                            historical_days,
                                            axis=0)

                ## calculate distance matrix (eudclidean)
                distance_to_avg = squareform(
                    pdist(data_to_compare, 'euclidean'))[0, :]

                ## identify day with minimum distance to average day
                min_distance_index_c[c - 1] = np.where(
                    distance_to_avg == np.min(distance_to_avg[
                        distance_to_avg > 0]))[0][0]
                min_distance_index_y[c - 1] = indices_in_cluster[
                    min_distance_index_c[c - 1] - 1]
                min_distance_day[c - 1, :] = historical_days[
                    min_distance_index_c[c - 1] - 1, :]

            # if there is only one day in cluster, then this is the representative day
            else:
                avg_day[c - 1, :] = data_in_days[indices_in_cluster, :]
                min_distance_day[c -
                                 1, :] = data_in_days[indices_in_cluster, :]

        # 5. Weighting representative days
        # --------------------------------
        # Representative days are weighten according to its cluster size to reflect
        # the fact that large clusters, containing many days, represent common events,
        # while smaller clusters represent occasional patterns.
        clusters_weight = np.zeros(number_of_clusters, dtype=int)
        for c in range(number_of_clusters):
            clusters_weight[c] = len(np.where(clusters == c + 1)[0])

        # 6. Deriving time series with representative days
        # ------------------------------------------------
        # A time series with the defined number of clusters is created and used for
        # the simulation.
        # Advantages: Less computational time, intraday behavior well represented
        # (thermal storage during the same day)
        # Disadvantages: Interday day behavior ist represented as representative days
        # are not consecutive and therefore do not represent the storage between days due to thermal capacity and/or solar gains.
        ## Time series
        timeseries_min = min_distance_day.flatten()
        timeseries_avg = avg_day.flatten()

        ## Time steps
        timesteps = np.array([
            np.arange(row_start[d], row_end[d]) for d in min_distance_index_y
        ]).flatten()

        if self.save >= 1:
            UrbanHeatPro.plot_typical_days(days_in_year, data_in_days, \
                Z, self.number_of_typ_days, \
                min_distance_day, avg_day, clusters, \
                clusters_per_month, month_names, \
                timeseries_min, timeseries_avg, self.result_dir)
            if self.debug != 0:
                print('  {}\TypicalDays'.format(self.result_dir))

        return timesteps, clusters_weight
Example #12
0
###
HOT_WATER = [[Tw], [hw_tank_limit, hw_flow]]

# 5. REPORTING
# 	0 No results saved or plotted
#	1 Results per simulation
#   2 Results per building
# 	3 Results per time step
plot = 0
save = 2
debug = 1
###
REPORTING = [plot, save, debug]

# MAIN
# --------------------------------------------------------------------------------
if __name__ == '__main__':

    # Simulation name
    NAME        = region + '_' + 'CF' + str(connection_factor) + \
           '_NSB' + str(_night_set_back) + '-' + str(T_nsb) + \
           '_intHG' + str(_internal_gains) + '_solHG' + str(_solar_gains) + \
           '_actPop' + str(_active_population) + \
           '_BL' + str(base_load/1e6) + 'MW_' + \
           '_dT' + str(dT_per_hour) + '_thI' + str(thermal_inertia)

    multiprocessing.freeze_support()
    my_Simulation = UrbanHeatPro.Simulation(NAME, SIMULATION, CITY,
                                            SPACE_HEATING, HOT_WATER,
                                            REPORTING)
    my_Simulation.run()
Example #13
0
    def initialize_dhw_probabilities(self):
        """
		Calculates dhw probabilities (daily consumption, event loads, flow rate and 
		duration as interpolate objects.
		"""

        # Daily specific dhw consumption [m3/m2 of living area]	as cdf
        x = [i[0] for i in self.building_stock_stats[1][0]]
        p = [i[1] for i in self.building_stock_stats[1][0]]
        dhw_cdf = UrbanHeatPro.create_interpolated_cdf(x, p)

        # Probability distribution of the DHW-load happening at specific time of the day
        #
        ### Probabilities in 0.2h-steps
        p_shower = [i[1] for i in self.building_stock_stats[1][1]]
        p_bath = [i[2] for i in self.building_stock_stats[1][1]]
        p_med_small = [i[3] for i in self.building_stock_stats[1][1]]
        #
        ### Interpolators
        x_min = 0.
        x_max = 23.8
        x_steps = 120
        x = np.linspace(x_min, x_max, num=x_steps, endpoint=False)
        shower_ptime = interpolate.interp1d(x, p_shower)
        bath_ptime = interpolate.interp1d(x, p_bath)
        medium_ptime = interpolate.interp1d(x, p_med_small)
        small_ptime = medium_ptime
        #
        prob_time = [shower_ptime, bath_ptime, medium_ptime, small_ptime]

        # Factor for probability distribution of the DHW-load happening at specific weekday
        shower_pwday = [i[1] for i in self.building_stock_stats[1][2]]
        bath_pwday = [i[2] for i in self.building_stock_stats[1][2]]
        medium_pwday = [i[3] for i in self.building_stock_stats[1][2]]
        small_pwday = medium_pwday
        prob_wday = [shower_pwday, bath_pwday, medium_pwday, small_pwday]

        # Load flow rate CDF
        x_min = 3.
        x_max = 20.
        x_steps = 1000
        x = np.linspace(x_min, x_max, num=x_steps, endpoint=False)
        ### Shower
        mean = self.building_stock_stats[1][3][0][0]
        sigma = self.building_stock_stats[1][3][1][0]
        norm_dist = UrbanHeatPro.create_normal_distribution(x, mean, sigma)
        shower_f_cdf = UrbanHeatPro.create_interpolated_cdf(x, norm_dist)
        #
        ### Bath
        mean = self.building_stock_stats[1][3][0][1]
        sigma = self.building_stock_stats[1][3][1][1]
        norm_dist = UrbanHeatPro.create_normal_distribution(x, mean, sigma)
        bath_f_cdf = UrbanHeatPro.create_interpolated_cdf(x, norm_dist)
        #
        x_min = 0.
        x_max = 10.
        x_steps = 1000
        x = np.linspace(x_min, x_max, num=x_steps, endpoint=False)
        ### Medium
        mean = self.building_stock_stats[1][3][0][2]
        sigma = self.building_stock_stats[1][3][1][2]
        norm_dist = UrbanHeatPro.create_normal_distribution(x, mean, sigma)
        medium_f_cdf = UrbanHeatPro.create_interpolated_cdf(x, norm_dist)
        #
        ### Small
        mean = self.building_stock_stats[1][3][0][3]
        sigma = self.building_stock_stats[1][3][1][3]
        norm_dist = UrbanHeatPro.create_normal_distribution(x, mean, sigma)
        small_f_cdf = UrbanHeatPro.create_interpolated_cdf(x, norm_dist)
        #
        flowRate_cdf = [shower_f_cdf, bath_f_cdf, medium_f_cdf, small_f_cdf]

        # Load duration CDF
        x_min = 3.
        x_max = 15.
        x_steps = 1000
        x = np.linspace(x_min, x_max, num=x_steps, endpoint=False)
        ### Shower
        mean = self.building_stock_stats[1][4][0][0]
        sigma = self.building_stock_stats[1][4][1][0]
        norm_dist = UrbanHeatPro.create_normal_distribution(x, mean, sigma)
        shower_d_cdf = UrbanHeatPro.create_interpolated_cdf(x, norm_dist)
        #
        ### Bath
        mean = self.building_stock_stats[1][4][0][1]
        sigma = self.building_stock_stats[1][4][1][1]
        norm_dist = UrbanHeatPro.create_normal_distribution(x, mean, sigma)
        bath_d_cdf = UrbanHeatPro.create_interpolated_cdf(x, norm_dist)
        #
        x_min = 0.
        x_max = 5.
        x_steps = 1000
        x = np.linspace(x_min, x_max, num=x_steps, endpoint=False)
        ### Medium
        mean = self.building_stock_stats[1][4][0][2]
        sigma = self.building_stock_stats[1][4][1][2]
        norm_dist = UrbanHeatPro.create_normal_distribution(x, mean, sigma)
        medium_d_cdf = UrbanHeatPro.create_interpolated_cdf(x, norm_dist)
        #
        ### Small
        mean = self.building_stock_stats[1][4][0][3]
        sigma = self.building_stock_stats[1][4][1][3]
        norm_dist = UrbanHeatPro.create_normal_distribution(x, mean, sigma)
        small_d_cdf = UrbanHeatPro.create_interpolated_cdf(x, norm_dist)
        #
        duration_cdf = [shower_d_cdf, bath_d_cdf, medium_d_cdf, small_d_cdf]

        dhw_prob = [dhw_cdf, prob_time, prob_wday, flowRate_cdf, duration_cdf]

        return dhw_prob
Example #14
0
	def analyze_thermal_properties_per_sim(self):
		"""
		Appends thermal properties for all runs and plot histograms
		"""
		
		# initialize temporal matrices
		U_res     = [[np.array([]) for col in range(4)] for row in range(10)]
		C_res     = [[np.array([]) for col in range(4)] for row in range(10)]
		TAU_res   = [[np.array([]) for col in range(4)] for row in range(10)]
		SH_res	  = [[np.array([]) for col in range(4)] for row in range(10)]
		HW_res	  = [[np.array([]) for col in range(4)] for row in range(10)]
		HEAT_res  = [[np.array([]) for col in range(4)] for row in range(10)]
		U_nres    = [np.array([]) for col in range(5)]
		C_nres    = [np.array([]) for col in range(5)]
		TAU_nres  = [np.array([]) for col in range(5)]
		SH_nres	  = [np.array([]) for col in range(5)]
		HW_nres	  = [np.array([]) for col in range(5)]
		HEAT_nres = [np.array([]) for col in range(5)]
		
		# append simulation values
		for run in range(self.N):
			
			# RESIDENTIAL
			for year_class in range(10):
				for btype in range(4):
				
					U_res[year_class][btype]    = np.append(U_res[year_class][btype], self.u_res[run][year_class][btype])
					C_res[year_class][btype]    = np.append(C_res[year_class][btype], self.c_res[run][year_class][btype])
					TAU_res[year_class][btype]  = np.append(TAU_res[year_class][btype], self.tau_res[run][year_class][btype])
					SH_res[year_class][btype]   = np.append(SH_res[year_class][btype], self.sh_per_area_res[run][year_class][btype])
					HW_res[year_class][btype]   = np.append(HW_res[year_class][btype], self.hw_per_area_res[run][year_class][btype])
					HEAT_res[year_class][btype] = np.append(HEAT_res[year_class][btype], self.heat_per_area_res[run][year_class][btype])
			
			# NON-RESIDENTIAL
			for year_class in range(5):
				
				U_nres[year_class] 		 = np.append(U_nres[year_class], self.u_nres[run][year_class])
				C_nres[year_class]		 = np.append(C_nres[year_class], self.c_nres[run][year_class])
				TAU_nres[year_class]	 = np.append(TAU_nres[year_class], self.tau_nres[run][year_class])
				SH_nres[year_class]		 = np.append(SH_nres[year_class], self.sh_per_area_nres[run][year_class])
				HW_nres[year_class]		 = np.append(HW_nres[year_class], self.hw_per_area_nres[run][year_class])
				HEAT_nres[year_class]	 = np.append(HEAT_nres[year_class], self.heat_per_area_nres[run][year_class])
		
		# plot histograms
		### RESIDENTIAL
		###### U-value [MW/K]
		figname = '{}/histU_res.png'.format(self.result_dir)
		UrbanHeatPro.plot_histogram_table(3, U_res, 'U-value [MW/K]', figname,
								factor = 1e6, figsize = (30, 25))
		###### U-value [MW/K]
		figname = '{}/histC_res.png'.format(self.result_dir)
		UrbanHeatPro.plot_histogram_table(3, C_res, 'Thermal mass [GJ/K]', figname,
								factor = 1e9, figsize = (30, 25))
		###### Tau [h]
		figname = '{}/histTau_res.png'.format(self.result_dir)
		UrbanHeatPro.plot_histogram_table(3, TAU_res, 'Tau [h]', figname,
								factor = 3600, figsize = (30, 25))
		###### Space heating demand per unit area [kWh/m2]
		figname = '{}/histSHD_perUnitArea_res.png'.format(self.result_dir)
		UrbanHeatPro.plot_histogram_table(3, SH_res, 'Energy [kWh/m2]', figname,
								factor = 1e3, figsize = (30, 25))
		###### Hot water demand per unit area [kWh/m2]
		figname = '{}/histHWD_perUnitArea_res.png'.format(self.result_dir)
		UrbanHeatPro.plot_histogram_table(3, HW_res, 'Energy [kWh/m2]', figname,
								factor = 1e3, figsize = (30, 25))
		###### Total heat demand per unit area [kWh/m2]
		figname = '{}/histHeat_perUnitArea_res.png'.format(self.result_dir)
		UrbanHeatPro.plot_histogram_table(3, HEAT_res, 'Energy [kWh/m2]', figname,
								factor = 1e3, figsize = (30, 25))
								
		### NON-RESIDENTIAL
		###### U-value [MW/K]
		figname = '{}/histU_nres.png'.format(self.result_dir)
		UrbanHeatPro.plot_histogram_table(0, U_nres, 'U-value [MW/K]', figname,
								factor = 1e6, figsize = (30, 25))
		###### U-value [MW/K]
		figname = '{}/histC_nres.png'.format(self.result_dir)
		UrbanHeatPro.plot_histogram_table(0, C_nres, 'Thermal mass [GJ/K]', figname,
								factor = 1e9, figsize = (30, 25))
		###### Tau [h]
		figname = '{}/histTau_nres.png'.format(self.result_dir)
		UrbanHeatPro.plot_histogram_table(0, TAU_nres, 'Tau [h]', figname,
								factor = 3600, figsize = (30, 25))
		###### Space heating demand per unit area [kWh/m2]
		figname = '{}/histSHD_perUnitArea_nres.png'.format(self.result_dir)
		UrbanHeatPro.plot_histogram_table(0, SH_nres, 'Energy [kWh/m2]', figname,
								factor = 1e3, figsize = (30, 25))
		###### Hot water demand per unit area [kWh/m2]
		figname = '{}/histHWD_perUnitArea_nres.png'.format(self.result_dir)
		UrbanHeatPro.plot_histogram_table(0, HW_nres, 'Energy [kWh/m2]', figname,
								factor = 1e3, figsize = (30, 25))
		###### Total heat demand per unit area [kWh/m2]
		figname = '{}/histHeat_perUnitArea_nres.png'.format(self.result_dir)
		UrbanHeatPro.plot_histogram_table(0, HEAT_nres, 'Energy [kWh/m2]', figname,
								factor = 1e3, figsize = (30, 25))
Example #15
0
	def analyze_thermal_properties_per_run(self, run, result_dir_run):
		"""
		Extracts data from object City and plots a histogram showing the values of the 
		thermal properties for all buildings in the city. Buildings are classified according 
		to year construction class and building type. Analyzed thermal parameters are: 
			U-value [W/K]
			Thermal mass [J/K] 
			Tau [s]
			Space heat demand per unit area [Wh/m2] 
			Hot water demand per unit area [Wh/m2]
			Total heat demand per unit area [Wh/m2]
		"""
	
		# extract data from City object
		for year_class in range(10):
			for btype in range(4):
			
				# extract all buildings B with specific year_class, btype and use
				c0  = self.my_city.energy_per_building[:, 1] == 3  # RESIDENTIAL
				c1  = self.my_city.energy_per_building[:, 2] == year_class
				c2  = self.my_city.energy_per_building[:, 3] == btype
				B   = self.my_city.energy_per_building[c0 * c1 * c2]
			
				# U-value [W/K]
				self.u_res[run][year_class][btype] = np.append(self.u_res[run][year_class][btype], \
														B[:, 13])
				# Thermal mass [J/K]
				self.c_res[run][year_class][btype] = np.append(self.c_res[run][year_class][btype], \
														B[:, 14])							
				# Tau [s]
				self.tau_res[run][year_class][btype] = np.append(self.tau_res[run][year_class][btype], \
														B[:, 15])	
				# Space heat demand per unit area [Wh/m2]
				self.sh_per_area_res[run][year_class][btype] = np.append(self.sh_per_area_res[run][year_class][btype], \
														(B[:, 16] / B[:, 5]))
				# Hot water demand per unit area [Wh/m2]
				self.hw_per_area_res[run][year_class][btype] = np.append(self.hw_per_area_res[run][year_class][btype], \
														(B[:, 17] / B[:, 5]))															 
				# Total heat demand per unit area [Wh/m2]
				self.heat_per_area_res[run][year_class][btype] = np.append(self.heat_per_area_res[run][year_class][btype], \
														(B[:, 18] / B[:, 5]))
		
		for year_class in range(5):
		
			# extract all buildings B with specific year_class, btype and use
			C0  = self.my_city.energy_per_building[:, 1] != 3  # NON-RESIDENTIAL
			c1  = self.my_city.energy_per_building[:, 2] == year_class
			B   = self.my_city.energy_per_building[c0 * c1]
														
			# U-value [W/K]
			self.u_nres[run][year_class] = np.append(self.u_nres[run][year_class], B[:, 13])
			# Thermal mass [J/K]
			self.c_nres[run][year_class] = np.append(self.c_nres[run][year_class], B[:, 14])							
			# Tau [s]
			self.tau_nres[run][year_class] = np.append(self.tau_nres[run][year_class], B[:, 15])
			# Space heat demand per unit area [Wh/m2]
			self.sh_per_area_nres[run][year_class] = np.append(self.sh_per_area_nres[run][year_class], \
														(B[:, 16] / B[:, 5]))
			# Hot water demand per unit area [Wh/m2]
			self.hw_per_area_nres[run][year_class] = np.append(self.hw_per_area_nres[run][year_class], \
														(B[:, 17] / B[:, 5]))															 
			# Total heat demand per unit area [Wh/m2]
			self.heat_per_area_nres[run][year_class] = np.append(self.heat_per_area_nres[run][year_class], \
														(B[:, 18] / B[:, 5]))													
		
		# plot histograms per run 
		### RESIDENTIAL
		###### U-value [MW/K]
		figname = '{}/histU_res_{}.png'.format(result_dir_run, run)
		UrbanHeatPro.plot_histogram_table(3, self.u_res[run], 'U-value [MW/K]', figname,
								factor = 1e6, figsize = (30, 25))
		###### U-value [MW/K]
		figname = '{}/histC_res_{}.png'.format(result_dir_run, run)
		UrbanHeatPro.plot_histogram_table(3, self.c_res[run], 'Thermal mass [GJ/K]', figname,
								factor = 1e9, figsize = (30, 25))
		###### Tau [h]
		figname = '{}/histTau_res_{}.png'.format(result_dir_run, run)
		UrbanHeatPro.plot_histogram_table(3, self.tau_res[run], 'Tau [h]', figname,
								factor = 3600, figsize = (30, 25))
		###### Space heating demand per unit area [kWh/m2]
		figname = '{}/histSHD_perUnitArea_res_{}.png'.format(result_dir_run, run)
		UrbanHeatPro.plot_histogram_table(3, self.sh_per_area_res[run], 'Energy [kWh/m2]', figname,
								factor = 1e3, figsize = (30, 25))
		###### Hot water demand per unit area [kWh/m2]
		figname = '{}/histHWD_perUnitArea_res_{}.png'.format(result_dir_run, run)
		UrbanHeatPro.plot_histogram_table(3, self.hw_per_area_res[run], 'Energy [kWh/m2]', figname,
								factor = 1e3, figsize = (30, 25))
		###### Total heat demand per unit area [kWh/m2]
		figname = '{}/histHeat_perUnitArea_res_{}.png'.format(result_dir_run, run)
		UrbanHeatPro.plot_histogram_table(3, self.heat_per_area_res[run], 'Energy [kWh/m2]', figname,
								factor = 1e3, figsize = (30, 25))
								
		### NON-RESIDENTIAL
		###### U-value [MW/K]
		figname = '{}/histU_nres_{}.png'.format(result_dir_run, run)
		UrbanHeatPro.plot_histogram_table(0, self.u_nres[run], 'U-value [MW/K]', figname,
								factor = 1e6, figsize = (30, 25))
		###### U-value [MW/K]
		figname = '{}/histC_nres_{}.png'.format(result_dir_run, run)
		UrbanHeatPro.plot_histogram_table(0, self.c_nres[run], 'Thermal mass [GJ/K]', figname,
								factor = 1e9, figsize = (30, 25))
		###### Tau [h]
		figname = '{}/histTau_nres_{}.png'.format(result_dir_run, run)
		UrbanHeatPro.plot_histogram_table(0, self.tau_nres[run], 'Tau [h]', figname,
								factor = 3600, figsize = (30, 25))
		###### Space heating demand per unit area [kWh/m2]
		figname = '{}/histSHD_perUnitArea_nres_{}.png'.format(result_dir_run, run)
		UrbanHeatPro.plot_histogram_table(0, self.sh_per_area_nres[run], 'Energy [kWh/m2]', figname,
								factor = 1e3, figsize = (30, 25))
		###### Hot water demand per unit area [kWh/m2]
		figname = '{}/histHWD_perUnitArea_nres_{}.png'.format(result_dir_run, run)
		UrbanHeatPro.plot_histogram_table(0, self.hw_per_area_nres[run], 'Energy [kWh/m2]', figname,
								factor = 1e3, figsize = (30, 25))
		###### Total heat demand per unit area [kWh/m2]
		figname = '{}/histHeat_perUnitArea_nres_{}.png'.format(result_dir_run, run)
		UrbanHeatPro.plot_histogram_table(0, self.heat_per_area_nres[run], 'Energy [kWh/m2]', figname,
								factor = 1e3, figsize = (30, 25))