import numpy as np
from . import sunlit_shaded_patches
import cupy as cp
[docs]
def define_patch_characteristics(solar_altitude, solar_azimuth,
patch_altitude, patch_azimuth, steradian,
asvf,
shmat, vegshmat, vbshvegshmat,
Lsky_down, Lsky_side, Lsky, Lup,
Ta, Tgwall, ewall,
rows, cols):
''' This unchanged function defines if a patch seen from a pixel is sky, building or vegetation.
It also calculates if a building patch is sunlit or shaded. From this it estimates
corresponding longwave radiation originating from each surface.'''
# Stefan-Boltzmann's Constant
SBC = 5.67051e-8
# Degrees to radians
deg2rad = np.pi / 180
# Define variables
Ldown_sky = cp.zeros((rows,cols))
Ldown_veg = cp.zeros((rows,cols))
Ldown_sun = cp.zeros((rows,cols))
Ldown_sh = cp.zeros((rows,cols))
Ldown_ref = cp.zeros((rows,cols))
Lside_sky = cp.zeros((rows,cols))
Lside_veg = cp.zeros((rows,cols))
Lside_sun = cp.zeros((rows,cols))
Lside_sh = cp.zeros((rows,cols))
Lside_ref = cp.zeros((rows,cols))
Least = cp.zeros((rows,cols))
Lwest = cp.zeros((rows,cols))
Lnorth = cp.zeros((rows,cols))
Lsouth = cp.zeros((rows,cols))
# Define patch characteristics (sky, vegetation or building, and sunlit or shaded if building)
for idx in range(patch_altitude.shape[0]):
# Calculations for patches on sky, shmat = 1 = sky is visible
temp_sky = ((shmat[:,:,idx] == 1) & (vegshmat[:,:,idx] == 1))
# Longwave radiation from sky to vertical surface
Ldown_sky += temp_sky * Lsky_down[idx,2]
# Longwave radiation from sky to horizontal surface
Lside_sky += temp_sky * Lsky_side[idx,2]
# Calculations for patches that are vegetation, vegshmat = 0 = shade from vegetation
temp_vegsh = ((vegshmat[:,:,idx] == 0) | (vbshvegshmat[:,:,idx] == 0))
# Longwave radiation from vegetation surface (considered vertical)
vegetation_surface = ((ewall * SBC * ((Ta + 273.15) ** 4)) / np.pi)
# Longwave radiation reaching a vertical surface
Lside_veg += vegetation_surface * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_vegsh
# Longwave radiation reaching a horizontal surface
Ldown_veg += vegetation_surface * steradian[idx] * np.sin(patch_altitude[idx] * deg2rad) * temp_vegsh
# Portion into cardinal directions to be used for standing box or POI output
if (patch_azimuth[idx] > 360) or (patch_azimuth[idx] < 180):
Least += temp_sky * Lsky_side[idx,2] * np.cos((90 - patch_azimuth[idx]) * deg2rad)
Least += vegetation_surface * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_vegsh * np.cos((90 - patch_azimuth[idx]) * deg2rad)
if (patch_azimuth[idx] > 90) and (patch_azimuth[idx] < 270):
Lsouth += temp_sky * Lsky_side[idx,2] * np.cos((180 - patch_azimuth[idx]) * deg2rad)
Lsouth += vegetation_surface * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_vegsh * np.cos((180 - patch_azimuth[idx]) * deg2rad)
if (patch_azimuth[idx] > 180) and (patch_azimuth[idx] < 360):
Lwest += temp_sky * Lsky_side[idx,2] * np.cos((270 - patch_azimuth[idx]) * deg2rad)
Lwest += vegetation_surface * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_vegsh * np.cos((270 - patch_azimuth[idx]) * deg2rad)
if (patch_azimuth[idx] > 270) or (patch_azimuth[idx] < 90):
Lnorth += temp_sky * Lsky_side[idx,2] * np.cos((0 - patch_azimuth[idx]) * deg2rad)
Lnorth += vegetation_surface * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_vegsh * np.cos((0 - patch_azimuth[idx]) * deg2rad)
# Calculations for patches that are buildings, shmat = 0 = shade from buildings
temp_vbsh = (1 - shmat[:,:,idx]) * vbshvegshmat[:,:,idx]
temp_sh = (temp_vbsh == 1)
azimuth_difference = np.abs(solar_azimuth - patch_azimuth[idx])
# Longwave radiation from sunlit surfaces
sunlit_surface = ((ewall * SBC * ((Ta + Tgwall + 273.15) ** 4)) / np.pi)
# Longwave radiation from shaded surfaces
shaded_surface = ((ewall * SBC * ((Ta + 273.15) ** 4)) / np.pi)
if ((azimuth_difference > 90) and (azimuth_difference < 270) and (solar_altitude > 0)):
# Calculate which patches defined as buildings that are sunlit or shaded
sunlit_patches, shaded_patches = sunlit_shaded_patches.shaded_or_sunlit(solar_altitude, solar_azimuth, patch_altitude[idx], patch_azimuth[idx], asvf)
# Calculate longwave radiation from sunlit walls to vertical surface
Lside_sun += sunlit_surface * sunlit_patches * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh
# Calculate longwave radiation from shaded walls to vertical surface
Lside_sh += shaded_surface * shaded_patches * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh
# Calculate longwave radiation from sunlit walls to horizontal surface
Ldown_sun += sunlit_surface * sunlit_patches * steradian[idx] * np.sin(patch_altitude[idx] * deg2rad) * temp_sh
# Calculate longwave radiation from shaded walls to horizontal surface
Ldown_sh += shaded_surface * shaded_patches * steradian[idx] * np.sin(patch_altitude[idx] * deg2rad) * temp_sh
# Portion into cardinal directions to be used for standing box or POI output
if (patch_azimuth[idx] > 360) or (patch_azimuth[idx] < 180):
Least += sunlit_surface * sunlit_patches * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh * np.cos((90 - patch_azimuth[idx]) * deg2rad)
Least += shaded_surface * shaded_patches * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh * np.cos((90 - patch_azimuth[idx]) * deg2rad)
if (patch_azimuth[idx] > 90) and (patch_azimuth[idx] < 270):
Lsouth += sunlit_surface * sunlit_patches * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh * np.cos((180 - patch_azimuth[idx]) * deg2rad)
Lsouth += shaded_surface * shaded_patches * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh * np.cos((180 - patch_azimuth[idx]) * deg2rad)
if (patch_azimuth[idx] > 180) and (patch_azimuth[idx] < 360):
Lwest += sunlit_surface * sunlit_patches * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh * np.cos((270 - patch_azimuth[idx]) * deg2rad)
Lwest += shaded_surface * shaded_patches * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh * np.cos((270 - patch_azimuth[idx]) * deg2rad)
if (patch_azimuth[idx] > 270) or (patch_azimuth[idx] < 90):
Lnorth += sunlit_surface * sunlit_patches * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh * np.cos((0 - patch_azimuth[idx]) * deg2rad)
Lnorth += shaded_surface * shaded_patches * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh * np.cos((0 - patch_azimuth[idx]) * deg2rad)
else:
# Calculate longwave radiation from shaded walls reaching a vertical surface
Lside_sh += shaded_surface * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh
# Calculate longwave radiation from shaded walls reaching a horizontal surface
Ldown_sh += shaded_surface * steradian[idx] * np.sin(patch_altitude[idx] * deg2rad) * temp_sh
# Portion into cardinal directions to be used for standing box or POI output
if (patch_azimuth[idx] > 360) or (patch_azimuth[idx] < 180):
Least += shaded_surface * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh * np.cos((90 - patch_azimuth[idx]) * deg2rad)
if (patch_azimuth[idx] > 90) and (patch_azimuth[idx] < 270):
Lsouth += shaded_surface * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh * np.cos((180 - patch_azimuth[idx]) * deg2rad)
if (patch_azimuth[idx] > 180) and (patch_azimuth[idx] < 360):
Lwest += shaded_surface * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh * np.cos((270 - patch_azimuth[idx]) * deg2rad)
if (patch_azimuth[idx] > 270) or (patch_azimuth[idx] < 90):
Lnorth += shaded_surface * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh * np.cos((0 - patch_azimuth[idx]) * deg2rad)
# Calculate reflected longwave in each patch
reflected_on_surfaces = (((Ldown_sky+Lup)*(1-ewall)*0.5) / np.pi)
for idx in range(patch_altitude.shape[0]):
temp_sh = ((shmat[:,:,idx] == 0) | (vegshmat[:,:,idx] == 0) | (vbshvegshmat[:,:,idx] == 0))
# Reflected longwave radiation reaching vertical surfaces
Lside_ref += reflected_on_surfaces * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh
# Reflected longwave radiation reaching horizontal surfaces
Ldown_ref += reflected_on_surfaces * steradian[idx] * np.sin(patch_altitude[idx] * deg2rad) * temp_sh
# Portion into cardinal directions to be used for standing box or POI output
if (patch_azimuth[idx] > 360) or (patch_azimuth[idx] < 180):
Least += reflected_on_surfaces * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh * np.cos((90 - patch_azimuth[idx]) * deg2rad)
if (patch_azimuth[idx] > 90) and (patch_azimuth[idx] < 270):
Lsouth += reflected_on_surfaces * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh * np.cos((180 - patch_azimuth[idx]) * deg2rad)
if (patch_azimuth[idx] > 180) and (patch_azimuth[idx] < 360):
Lwest += reflected_on_surfaces * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh * np.cos((270 - patch_azimuth[idx]) * deg2rad)
if (patch_azimuth[idx] > 270) or (patch_azimuth[idx] < 90):
Lnorth += reflected_on_surfaces * steradian[idx] * np.cos(patch_altitude[idx] * deg2rad) * temp_sh * np.cos((0 - patch_azimuth[idx]) * deg2rad)
# Sum of all Lside components (sky, vegetation, sunlit and shaded buildings, reflected)
Lside = Lside_sky + Lside_veg + Lside_sh + Lside_sun + Lside_ref
# Sum of all Lside components (sky, vegetation, sunlit and shaded buildings, reflected)
Ldown = Ldown_sky + Ldown_veg + Ldown_sh + Ldown_sun + Ldown_ref
return Ldown, Lside, Lside_sky, Lside_veg, Lside_sh, Lside_sun, Lside_ref, Least, Lwest, Lnorth, Lsouth