Source code for uwg.UCMDef

"""Class for Urban Canopy Model."""
from __future__ import division

try:
    range = xrange
except NameError:
    pass

from math import sqrt, pow
import copy


[docs]class UCMDef(object): """Definition of Urban Canopy - Building Energy Model Class Args: bldHeight: Average building height (m). bldDensity: Horizontal building density (footprint/total_area). verToHor: Vertical-to-horizontal urban area ratio (facade area/urban area). treeCoverage: Horizontal tree density (footprint). sensAnthrop: Sensible anthropogenic heat (other than from buildings) (W m-2). latAnthrop: Latent anthropogenic heat (other than from buildings) (W m-2). initialTemp: Canyon air temperature (db) (K). initialHum: Canyon specific humidity (kg kg-1). initialWind: Urban canyon wind velocity (m s-1). parameter: Param object. r_glaze: Area-weighted average of glazing ratio from urban building stock. SHGC: Area-weighted average of SHGC from urban building stock. alb_wall: Area-weighted average of wall albedo from urban building stock. road: Road element class (moved from BEM). Properties * road -- Road element class (moved from BEM) * # Urban Canyon Parameters * bldHeight -- average building height (m) * bldDensity -- horizontal building density (footprint) * verToHor -- vertical-to-horizontal urban area ratio (facade area/urban area) * treeCoverage -- horizontal tree density (footprint) * sensAnthrop -- sensible anthropogenic heat (other than from buildings) (W m-2) * latAnthrop -- latent anthropogenic heat (other than from buildings) (W m-2) * z0u -- urban roughness length (m) * l_disp -- urban displacement length (m) * roadShad -- shadowing of roads * canWidth -- canyon width (m) * bldWidth -- bld width (m) * canAspect -- canyon aspect ratio * roadConf -- road-sky configuration factors (sky view factor) * alb_wall -- average wall albedo * wallConf -- wall-sky configuration factors (sky view factor) * VFwallroad -- wall-road view factor * VFroadwall -- road-wall view factor * facArea -- facade area (m2) * roadArea -- road area (m2) * roofArea -- roof area (m2) (also building area) * facAbsor -- average facade absortivity * roadAbsor -- average road absortivity * h_mix -- waste heat mix into canyon ratio * # Urban Canyon Variables * canTemp -- canyon air temperature (db) (K) * Tdp -- dew point temperature * Twb -- wetbulb temperature * canHum -- canyon specific humidity (kg kg-1) * canRHum -- canyon relative humidity () * canWind -- urban canyon wind velocity (m s-1) * turbU -- canyon turbulent velocities (m s-1) * turbV -- canyon turbulent velocities (m s-1) * turbW -- canyon turbulent velocities (m s-1) * ublTemp -- urban boundary layer temperature (K) * ublTempdx -- urban boundary layer temperature discretization (K) * ublWind -- urban boundary layer wind velocity (m s-1) * ustar -- friction velocity (m s-1) * ustarMod -- modified friction velocity (m s-1) * uExch -- exchange velocity (m s-1) * treeLatHeat -- latent heat from trees (W m-2) * treeSensHeat -- sensible heat from trees (W m-2) * sensHeat -- urban sensible heat (W m-2) * latHeat -- urban latent heat (W m-2) * windProf -- urban wind profile * Q_roof -- sensible heat flux from building roof (convective) * Q_wall -- sensible heat flux from building wall (convective) * Q_window -- sensible heat flux from building window (via U-factor) * Q_road -- sensible heat flux from road (convective) * Q_hvac -- sensible heat flux from HVAC waste * Q_traffic -- sensible heat flux from traffic (net) * Q_ubl -- Convective heat exchange with UBL layer * Q_vent -- Convective heat exchange from ventilation/infiltration * SolRecWall -- Solar received by wall * SolRecRoof -- Solar received by roof * SolRecRoad -- Solar received by road * roadTemp -- average road temperature (K) * roofTemp -- average roof temperature (K) * wallTemp -- average wall temperature (K) * ElecTotal -- Total Electricity consumption of urban area * GasTotal -- Total Gas consumption of the urban area """ def __init__(self, bldHeight, bldDensity, verToHor, treeCoverage, sensAnthrop, latAnthrop, initialTemp, initialHum, initialWind, parameter, r_glaze, SHGC, alb_wall, road): self.road = road self.bldHeight = bldHeight self.verToHor = verToHor self.bldDensity = bldDensity self.treeCoverage = treeCoverage self.vegcover = (1 - self.bldDensity) * self.road.vegcoverage self.sensAnthrop = sensAnthrop self.latAnthrop = latAnthrop self.roadShad = min(treeCoverage / (1 - bldDensity), 1) # UWG_Matlab assumes bld_area = square, so sqrt(bld_area) = side length # bld width: (side length) derived from bldDensity and verToHor (m) self.bldWidth = 4 * bldHeight * bldDensity / verToHor # urban area width == sqrt(bldDensity) == \ # ratio of bld footprint_width / urban area footprint d = self.bldWidth / (sqrt(bldDensity)) # canyon width (m) = urban area width - building width self.canWidth = d - self.bldWidth self.canAspect = bldHeight / self.canWidth self.roadConf = pow(pow(self.canAspect, 2) + 1, 0.5) - self.canAspect self.wallConf = ( 0.5 * (self.canAspect + 1 - pow(pow(self.canAspect, 2) + 1, 0.5)) / self.canAspect) self.facArea = 4 * self.bldWidth * bldHeight self.roadArea = d * d - pow(self.bldWidth, 2) self.roofArea = pow(self.bldWidth, 2) self.canTemp = initialTemp self.roadTemp = initialTemp self.canHum = initialHum self.ublWind = max(initialWind, parameter.windMin) self.canWind = initialWind self.ustar = 0.1 * initialWind self.ustarMod = 0.1 * initialWind # Calculate z0u = urban roughness length (m) frontDens = verToHor / 4. # density of just street facing facade if frontDens < 0.15: self.z0u = frontDens * self.bldHeight else: self.z0u = 0.15 * self.bldHeight # Calculate l_dsp = urban displacement length (m) if frontDens < 0.05: self.l_disp = 3 * frontDens * self.bldHeight elif frontDens < 0.15: self.l_disp = (0.15 + 5.5 * (frontDens - 0.05)) * self.bldHeight elif frontDens < 1: self.l_disp = (0.7 + 0.35 * (frontDens - 0.15)) * self.bldHeight else: self.l_disp = 0.5 * self.bldHeight self.alb_wall = alb_wall self.facAbsor = (1 - r_glaze) * (1 - alb_wall) + r_glaze * (1 - 0.75 * SHGC) self.roadAbsor = (1 - road.vegcoverage) * (1 - road.albedo) self.sensHeat = 0.0 # Variables set in urbflux function self.latHeat = None self.windProf = [] self.canRHum = None self.Tdp = None
[docs] def UCModel(self, BEM, T_ubl, forc, parameter): """Calculate the urban canyon temperature per The uwg (2012) Eq. 10.""" # air density dens = \ forc.pres / (1000 * 0.287042 * self.canTemp * (1. + 1.607858 * self.canHum)) dens_ubl = forc.pres / (1000 * 0.287042 * T_ubl * (1. + 1.607858 * forc.hum)) Cp_air = parameter.cp self.Q_wall = 0. self.Q_window = 0. self.Q_road = 0. self.Q_hvac = 0. self.Q_traffic = 0. self.Q_vent = 0. self.Q_ubl = 0. self.ElecTotal = 0. self.GasTotal = 0. self.roofTemp = 0. self.wallTemp = 0. # Road to Canyon T_road = self.road.layerTemp[0] h_conv = self.road.aeroCond H1 = T_road * h_conv * self.roadArea # Heat (Sens) from road surface H2 = h_conv * self.roadArea H1 = H1 + T_ubl * self.roadArea * self.uExch * Cp_air * dens_ubl # Heat from UBL H2 = H2 + self.roadArea * self.uExch * Cp_air * dens_ubl # W = m2 * W/m2 Q = (self.roofArea + self.roadArea) * (self.sensAnthrop + self.treeSensHeat) # Building energy output to canyon, in terms of absolute (total) values for j in range(len(BEM)): # Re-naming variable for readability building = BEM[j].building wall = BEM[j].wall T_indoor = building.indoor_temp T_wall = wall.layerTemp[0] R_glazing = building.glazing_ratio A_wall = (1. - R_glazing) * self.facArea A_window = R_glazing*self.facArea U_window = building.u_value H1 = H1 + BEM[j].frac*( T_indoor * A_window * U_window + # window U T_wall * A_wall * h_conv + # wall conv (T_indoor * self.roofArea * BEM[j].building.vent * BEM[j].building.nFloor * Cp_air * dens) + # Vent (T_indoor * self.roofArea * BEM[j].building.infil * self.bldHeight / 3600.0 * Cp_air * dens)) # Infil H2 = H2 + BEM[j].frac * ( A_window * U_window + # window U A_wall * h_conv + # wall conv (self.roofArea * BEM[j].building.vent * BEM[j].building.nFloor * Cp_air * dens) + # Vent (self.roofArea * BEM[j].building.infil * self.bldHeight / 3600.0 * Cp_air * dens)) # Infil Q = Q + BEM[j].frac * ( self.roofArea * building.sensWaste * self.h_mix + # HVAC waste heat # heat that didn't make it to inside A_window * BEM[j].wall.solRec * (1.0 - BEM[j].building.shgc)) self.wallTemp = self.wallTemp + BEM[j].frac * T_wall self.roofTemp = self.roofTemp + BEM[j].frac * BEM[j].roof.layerTemp[0] self.Q_ubl = (self.Q_ubl + BEM[j].frac * self.bldDensity * (BEM[j].roof.sens + BEM[j].building.sensWaste * (1. - self.h_mix))) # Changed by Jiachen Mao in March 2017 # Solve for canyon temperature self.canTemp = (H1 + Q) / H2 # Heat flux based per m^2 of urban area # Sensible heat from road (W/m^2 of urban area) self.Q_road = h_conv * (T_road - self.canTemp) * (1. - self.bldDensity) self.Q_ubl = ( self.Q_ubl + self.uExch * Cp_air * dens * (self.canTemp - T_ubl) * (1. - self.bldDensity)) self.Q_wall = h_conv * (self.wallTemp - self.canTemp) * self.verToHor self.Q_traffic = self.sensAnthrop # Building energy output to canyon, per m^2 of urban area T_can = copy.copy(self.canTemp) for j in range(len(BEM)): # ventilation volume per m^2 of building V_vent = BEM[j].building.vent * BEM[j].building.nFloor V_infil = BEM[j].building.infil * self.bldHeight / 3600.0 T_indoor = BEM[j].building.indoor_temp U_window = BEM[j].building.u_value # Added by Jiachen Mao in 03/17 R_glazing = BEM[j].building.glazing_ratio # Changed by Jiachen Mao in 03/17 self.Q_window = (self.Q_window + BEM[j].frac * self.verToHor * R_glazing * U_window * (T_indoor - T_can)) self.Q_window = (self.Q_window + BEM[j].frac * self.verToHor * R_glazing * BEM[j].wall.solRec * (1. - BEM[j].building.shgc)) self.Q_vent = (self.Q_vent + BEM[j].frac * self.bldDensity * Cp_air * dens * (V_vent + V_infil) * (T_indoor - T_can)) self.Q_hvac = (self.Q_hvac + BEM[j].frac * self.bldDensity * BEM[j].building.sensWaste * self.h_mix) self.Q_roof = self.Q_roof + BEM[j].frac * self.bldDensity * BEM[j].roof.sens # Total Electrical & Gas power in MW self.ElecTotal = \ self.ElecTotal + BEM[j].fl_area * BEM[j].building.ElecTotal / 1.e6 self.GasTotal = \ self.GasTotal + BEM[j].fl_area * BEM[j].building.GasTotal / 1.e6 # ------------------------------------------------------------------------------ # Sensible Heat # Note 1: In the current uwg code, latent heat from evapotranspiration, stagnant # water, or anthropogenic sources is not modeled due to the difficulty of # validation, and lack of reliability of precipitation data from EPW files. # Note 2: Changed sensHeat to multiply treeSensHeat by treeCoverage fraction. # Since treeSensHeat calculated in solarcalcs does not multiply sensheat by tree # fraction. For example, if there were 0 trees, this value should be 0. # ------------------------------------------------------------------------------ self.sensHeat = ( self.Q_wall + self.Q_road + self.Q_vent + self.Q_window + self.Q_hvac + self.Q_traffic + self.treeSensHeat + self.Q_roof) # Error checking if self.canTemp > 350. or self.canTemp < 200: raise Exception('Got canyon temperature at {} C. Something obviously went ' 'wrong (UCMDef.py).'.format(self.canTemp - 273.15))
def __repr__(self): return 'UCMDef,\n verToHor: {}\n bldDensity: {}\n bldHeight: {}\n canWidth: ' \ '{}\n canAspect: {}\n facArea: {}\n roofArea: {}'.format( self.verToHor, self.bldDensity, self.bldHeight, self.canWidth, self.canAspect, self.facArea, self.roofArea)