Source code for pythermalcomfort.models.solar_gain

import math
from pythermalcomfort.utilities import transpose_sharp_altitude


[docs]def solar_gain( sol_altitude, sharp, sol_radiation_dir, sol_transmittance, f_svv, f_bes, asw=0.7, posture="seated", floor_reflectance=0.6, ): """Calculates the solar gain to the human body using the Effective Radiant Field ( ERF) [1]_. The ERF is a measure of the net energy flux to or from the human body. ERF is expressed in W over human body surface area [w/m2]. In addition, it calculates the delta mean radiant temperature. Which is the amount by which the mean radiant temperature of the space should be increased if no solar radiation is present. Parameters ---------- sol_altitude : float Solar altitude, degrees from horizontal [deg]. Ranges between 0 and 90. sharp : float Solar horizontal angle relative to the front of the person (SHARP) [deg]. Ranges between 0 and 180 and is symmetrical on either side. Zero (0) degrees represents direct-beam radiation from the front, 90 degrees represents direct-beam radiation from the side, and 180 degrees rep- resent direct-beam radiation from the back. SHARP is the angle between the sun and the person only. Orientation relative to compass or to room is not included in SHARP. posture : str Default 'seated' list of available options 'standing', 'supine' or 'seated' sol_radiation_dir : float Direct-beam solar radiation, [W/m2]. Ranges between 200 and 1000. See Table C2-3 of ASHRAE 55 2020 [1]_. sol_transmittance : float Total solar transmittance, ranges from 0 to 1. The total solar transmittance of window systems, including glazing unit, blinds, and other façade treatments, shall be determined using one of the following methods: i) Provided by manufacturer or from the National Fenestration Rating Council approved Lawrence Berkeley National Lab International Glazing Database. ii) Glazing unit plus venetian blinds or other complex or unique shades shall be calculated using National Fenestration Rating Council approved software or Lawrence Berkeley National Lab Complex Glazing Database. f_svv : float Fraction of sky-vault view fraction exposed to body, ranges from 0 to 1. It can be calculated using the function :py:meth:`pythermalcomfort.utilities.f_svv`. f_bes : float Fraction of the possible body surface exposed to sun, ranges from 0 to 1. See Table C2-2 and equation C-7 ASHRAE 55 2020 [1]_. asw: float The average short-wave absorptivity of the occupant. It will range widely, depending on the color of the occupant’s skin as well as the color and amount of clothing covering the body. A value of 0.7 shall be used unless more specific information about the clothing or skin color of the occupants is available. Note: Short-wave absorptivity typically ranges from 0.57 to 0.84, depending on skin and clothing color. More information is available in Blum (1945). floor_reflectance: float Floor refectance. It is assumed to be constant and equal to 0.6. Notes ----- More information on the calculation procedure can be found in Appendix C of [1]_. Returns ------- erf: float Solar gain to the human body using the Effective Radiant Field [W/m2] delta_mrt: float Delta mean radiant temperature. The amount by which the mean radiant temperature of the space should be increased if no solar radiation is present. Examples -------- .. code-block:: python >>> from pythermalcomfort.models import solar_gain >>> results = solar_gain(sol_altitude=0, sharp=120, sol_radiation_dir=800, sol_transmittance=0.5, f_svv=0.5, f_bes=0.5, asw=0.7, posture='seated') >>> print(results) {'erf': 42.9, 'delta_mrt': 10.3} """ posture = posture.lower() if posture not in ["standing", "supine", "seated"]: raise ValueError("Posture has to be either standing, supine or seated") def find_span(arr, x): for i in range(0, len(arr)): if arr[i + 1] >= x >= arr[i]: return i return -1 deg_to_rad = 0.0174532925 hr = 6 i_diff = 0.2 * sol_radiation_dir # fp is the projected area factor fp_table = [ [0.35, 0.35, 0.314, 0.258, 0.206, 0.144, 0.082], [0.342, 0.342, 0.31, 0.252, 0.2, 0.14, 0.082], [0.33, 0.33, 0.3, 0.244, 0.19, 0.132, 0.082], [0.31, 0.31, 0.275, 0.228, 0.175, 0.124, 0.082], [0.283, 0.283, 0.251, 0.208, 0.16, 0.114, 0.082], [0.252, 0.252, 0.228, 0.188, 0.15, 0.108, 0.082], [0.23, 0.23, 0.214, 0.18, 0.148, 0.108, 0.082], [0.242, 0.242, 0.222, 0.18, 0.153, 0.112, 0.082], [0.274, 0.274, 0.245, 0.203, 0.165, 0.116, 0.082], [0.304, 0.304, 0.27, 0.22, 0.174, 0.121, 0.082], [0.328, 0.328, 0.29, 0.234, 0.183, 0.125, 0.082], [0.344, 0.344, 0.304, 0.244, 0.19, 0.128, 0.082], [0.347, 0.347, 0.308, 0.246, 0.191, 0.128, 0.082], ] if posture == "seated": fp_table = [ [0.29, 0.324, 0.305, 0.303, 0.262, 0.224, 0.177], [0.292, 0.328, 0.294, 0.288, 0.268, 0.227, 0.177], [0.288, 0.332, 0.298, 0.29, 0.264, 0.222, 0.177], [0.274, 0.326, 0.294, 0.289, 0.252, 0.214, 0.177], [0.254, 0.308, 0.28, 0.276, 0.241, 0.202, 0.177], [0.23, 0.282, 0.262, 0.26, 0.233, 0.193, 0.177], [0.216, 0.26, 0.248, 0.244, 0.22, 0.186, 0.177], [0.234, 0.258, 0.236, 0.227, 0.208, 0.18, 0.177], [0.262, 0.26, 0.224, 0.208, 0.196, 0.176, 0.177], [0.28, 0.26, 0.21, 0.192, 0.184, 0.17, 0.177], [0.298, 0.256, 0.194, 0.174, 0.168, 0.168, 0.177], [0.306, 0.25, 0.18, 0.156, 0.156, 0.166, 0.177], [0.3, 0.24, 0.168, 0.152, 0.152, 0.164, 0.177], ] if posture == "supine": sharp, sol_altitude = transpose_sharp_altitude(sharp, sol_altitude) alt_range = [0, 15, 30, 45, 60, 75, 90] az_range = [0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180] alt_i = find_span(alt_range, sol_altitude) az_i = find_span(az_range, sharp) fp11 = fp_table[az_i][alt_i] fp12 = fp_table[az_i][alt_i + 1] fp21 = fp_table[az_i + 1][alt_i] fp22 = fp_table[az_i + 1][alt_i + 1] az1 = az_range[az_i] az2 = az_range[az_i + 1] alt1 = alt_range[alt_i] alt2 = alt_range[alt_i + 1] fp = fp11 * (az2 - sharp) * (alt2 - sol_altitude) fp += fp21 * (sharp - az1) * (alt2 - sol_altitude) fp += fp12 * (az2 - sharp) * (sol_altitude - alt1) fp += fp22 * (sharp - az1) * (sol_altitude - alt1) fp /= (az2 - az1) * (alt2 - alt1) f_eff = 0.725 # fraction of the body surface exposed to environmental radiation if posture == "seated": f_eff = 0.696 sw_abs = asw lw_abs = 0.95 e_diff = f_eff * f_svv * 0.5 * sol_transmittance * i_diff e_direct = f_eff * fp * sol_transmittance * f_bes * sol_radiation_dir e_reflected = ( f_eff * f_svv * 0.5 * sol_transmittance * (sol_radiation_dir * math.sin(sol_altitude * deg_to_rad) + i_diff) * floor_reflectance ) e_solar = e_diff + e_direct + e_reflected erf = e_solar * (sw_abs / lw_abs) d_mrt = erf / (hr * f_eff) return {"erf": round(erf, 1), "delta_mrt": round(d_mrt, 1)}